Blame view

drivers/iio/industrialio-core.c 45 KB
d2912cb15   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
2
3
4
5
  /* The industrial I/O core
   *
   * Copyright (c) 2008 Jonathan Cameron
   *
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
6
7
   * Based on elements of hwmon and input subsystems.
   */
3176dd5d3   Sachin Kamat   iio: core: Use pr...
8
  #define pr_fmt(fmt) "iio-core: " fmt
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
9
10
11
12
13
14
15
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/idr.h>
  #include <linux/kdev_t.h>
  #include <linux/err.h>
  #include <linux/device.h>
  #include <linux/fs.h>
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
16
  #include <linux/poll.h>
fb1589710   Andy Shevchenko   iio: Allow to rea...
17
  #include <linux/property.h>
ffc18afa1   Jonathan Cameron   Staging: iio: Fix...
18
  #include <linux/sched.h>
4439c9353   Jeff Mahoney   staging: Complete...
19
  #include <linux/wait.h>
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
20
  #include <linux/cdev.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
21
  #include <linux/slab.h>
8e7d96724   Jonathan Cameron   staging: iio: rem...
22
  #include <linux/anon_inodes.h>
e553f182d   Michael Hennerich   staging: iio: cor...
23
  #include <linux/debugfs.h>
08a338055   Alison Schofield   iio: core: implem...
24
  #include <linux/mutex.h>
06458e277   Jonathan Cameron   IIO: Move core he...
25
  #include <linux/iio/iio.h>
df9c1c42c   Jonathan Cameron   staging:iio: Intr...
26
  #include "iio_core.h"
6aea1c364   Jonathan Cameron   staging:iio:renam...
27
  #include "iio_core_trigger.h"
06458e277   Jonathan Cameron   IIO: Move core he...
28
29
  #include <linux/iio/sysfs.h>
  #include <linux/iio/events.h>
9e69c935f   Lars-Peter Clausen   iio: Add referenc...
30
  #include <linux/iio/buffer.h>
33dd94cb9   Jonathan Cameron   iio:buffer.h - sp...
31
  #include <linux/iio/buffer_impl.h>
9dd1cb303   Jonathan Cameron   staging:iio: push...
32

99698b456   Peter Meerwald   iio: whitespace c...
33
  /* IDA to assign each registered device a unique id */
b156cf70e   Jonathan Cameron   staging: iio: con...
34
  static DEFINE_IDA(iio_ida);
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
35

f625cb97d   Jonathan Cameron   staging: iio: rem...
36
  static dev_t iio_devt;
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
37
38
  
  #define IIO_DEV_MAX 256
5aaaeba82   Jonathan Cameron   staging: iio: Mov...
39
  struct bus_type iio_bus_type = {
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
40
  	.name = "iio",
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
41
  };
5aaaeba82   Jonathan Cameron   staging: iio: Mov...
42
  EXPORT_SYMBOL(iio_bus_type);
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
43

e553f182d   Michael Hennerich   staging: iio: cor...
44
  static struct dentry *iio_debugfs_dentry;
c6fc80624   Jonathan Cameron   staging:iio: ABI ...
45
46
47
48
  static const char * const iio_direction[] = {
  	[0] = "in",
  	[1] = "out",
  };
ade7ef7ba   Jonathan Cameron   staging:iio: Diff...
49
  static const char * const iio_chan_type_name_spec[] = {
c6fc80624   Jonathan Cameron   staging:iio: ABI ...
50
  	[IIO_VOLTAGE] = "voltage",
faf290e86   Michael Hennerich   staging:iio: Add ...
51
52
  	[IIO_CURRENT] = "current",
  	[IIO_POWER] = "power",
9bff02f8f   Bryan Freed   staging:iio: Reor...
53
  	[IIO_ACCEL] = "accel",
41ea040c7   Jonathan Cameron   staging:iio: rena...
54
  	[IIO_ANGL_VEL] = "anglvel",
1d892719e   Jonathan Cameron   staging:iio: allo...
55
  	[IIO_MAGN] = "magn",
9bff02f8f   Bryan Freed   staging:iio: Reor...
56
57
  	[IIO_LIGHT] = "illuminance",
  	[IIO_INTENSITY] = "intensity",
f09f2c814   Bryan Freed   staging:iio: Add ...
58
  	[IIO_PROXIMITY] = "proximity",
9bff02f8f   Bryan Freed   staging:iio: Reor...
59
  	[IIO_TEMP] = "temp",
1d892719e   Jonathan Cameron   staging:iio: allo...
60
61
  	[IIO_INCLI] = "incli",
  	[IIO_ROT] = "rot",
1d892719e   Jonathan Cameron   staging:iio: allo...
62
  	[IIO_ANGL] = "angl",
9bff02f8f   Bryan Freed   staging:iio: Reor...
63
  	[IIO_TIMESTAMP] = "timestamp",
66dbe7043   Jonathan Cameron   staging:iio: Add ...
64
  	[IIO_CAPACITANCE] = "capacitance",
a6b12855b   Michael Hennerich   iio: core: Introd...
65
  	[IIO_ALTVOLTAGE] = "altvoltage",
21cd1fab0   Jon Brenner   IIO channel type ...
66
  	[IIO_CCT] = "cct",
c4f0c6936   Lars-Peter Clausen   iio: Add pressure...
67
  	[IIO_PRESSURE] = "pressure",
ac216aa29   Harald Geyer   iio: Add support ...
68
  	[IIO_HUMIDITYRELATIVE] = "humidityrelative",
55aebeb92   Daniel Baluta   iio: core: Introd...
69
  	[IIO_ACTIVITY] = "activity",
a88bfe785   Irina Tirdea   iio: core: Introd...
70
  	[IIO_STEPS] = "steps",
72c666446   Irina Tirdea   iio: core: Introd...
71
  	[IIO_ENERGY] = "energy",
cc3c9eeca   Irina Tirdea   iio: core: Introd...
72
  	[IIO_DISTANCE] = "distance",
5a1a93298   Irina Tirdea   iio: core: Introd...
73
  	[IIO_VELOCITY] = "velocity",
8ff6b3bc9   Matt Ranostay   iio: chemical: Ad...
74
  	[IIO_CONCENTRATION] = "concentration",
d38d54692   Matt Ranostay   iio: resistance: ...
75
  	[IIO_RESISTANCE] = "resistance",
ecb3a7ccc   Matt Ranostay   iio: ph: add IIO_...
76
  	[IIO_PH] = "ph",
d409404cf   Peter Meerwald-Stadler   iio: Add channel ...
77
  	[IIO_UVINDEX] = "uvindex",
4b9d2090a   Matt Ranostay   iio: electricalco...
78
  	[IIO_ELECTRICALCONDUCTIVITY] = "electricalconductivity",
1a8f324aa   William Breathitt Gray   iio: Implement co...
79
80
  	[IIO_COUNT] = "count",
  	[IIO_INDEX] = "index",
571299d09   Song Hongyan   iio: Add channel ...
81
  	[IIO_GRAVITY]  = "gravity",
3055a6cfa   Eugen Hristev   iio: Add channel ...
82
  	[IIO_POSITIONRELATIVE]  = "positionrelative",
c73314e6e   Mathieu Othacehe   iio: Add channel ...
83
  	[IIO_PHASE] = "phase",
17abc9ec6   Tomasz Duszynski   iio: add IIO_MASS...
84
  	[IIO_MASSCONCENTRATION] = "massconcentration",
1d892719e   Jonathan Cameron   staging:iio: allo...
85
  };
330c6c57e   Jonathan Cameron   staging:iio:event...
86
  static const char * const iio_modifier_names[] = {
1d892719e   Jonathan Cameron   staging:iio: allo...
87
88
89
  	[IIO_MOD_X] = "x",
  	[IIO_MOD_Y] = "y",
  	[IIO_MOD_Z] = "z",
4b8d80157   Peter Meerwald   iio: Add missing ...
90
91
92
93
94
95
96
97
  	[IIO_MOD_X_AND_Y] = "x&y",
  	[IIO_MOD_X_AND_Z] = "x&z",
  	[IIO_MOD_Y_AND_Z] = "y&z",
  	[IIO_MOD_X_AND_Y_AND_Z] = "x&y&z",
  	[IIO_MOD_X_OR_Y] = "x|y",
  	[IIO_MOD_X_OR_Z] = "x|z",
  	[IIO_MOD_Y_OR_Z] = "y|z",
  	[IIO_MOD_X_OR_Y_OR_Z] = "x|y|z",
8f5879b20   Jonathan Cameron   IIO: Add a modifi...
98
  	[IIO_MOD_ROOT_SUM_SQUARED_X_Y] = "sqrt(x^2+y^2)",
cf82cb812   Jonathan Cameron   IIO: Add a modifi...
99
  	[IIO_MOD_SUM_SQUARED_X_Y_Z] = "x^2+y^2+z^2",
330c6c57e   Jonathan Cameron   staging:iio:event...
100
101
  	[IIO_MOD_LIGHT_BOTH] = "both",
  	[IIO_MOD_LIGHT_IR] = "ir",
21cd1fab0   Jon Brenner   IIO channel type ...
102
103
104
105
  	[IIO_MOD_LIGHT_CLEAR] = "clear",
  	[IIO_MOD_LIGHT_RED] = "red",
  	[IIO_MOD_LIGHT_GREEN] = "green",
  	[IIO_MOD_LIGHT_BLUE] = "blue",
2c5ff1f9a   Peter Meerwald-Stadler   iio: Add modifier...
106
  	[IIO_MOD_LIGHT_UV] = "uv",
c0e4e0fd9   Maxime Roussin-BĂ©langer   iio: Add modifier...
107
  	[IIO_MOD_LIGHT_DUV] = "duv",
5082f405b   Srinivas Pandruvada   IIO: core: Add qu...
108
  	[IIO_MOD_QUATERNION] = "quaternion",
638b43b34   Peter Meerwald   iio: Add TEMP_AMB...
109
110
  	[IIO_MOD_TEMP_AMBIENT] = "ambient",
  	[IIO_MOD_TEMP_OBJECT] = "object",
11b8ddab8   Reyad Attiyat   iio: types: Added...
111
112
113
114
  	[IIO_MOD_NORTH_MAGN] = "from_north_magnetic",
  	[IIO_MOD_NORTH_TRUE] = "from_north_true",
  	[IIO_MOD_NORTH_MAGN_TILT_COMP] = "from_north_magnetic_tilt_comp",
  	[IIO_MOD_NORTH_TRUE_TILT_COMP] = "from_north_true_tilt_comp",
55aebeb92   Daniel Baluta   iio: core: Introd...
115
116
117
118
  	[IIO_MOD_RUNNING] = "running",
  	[IIO_MOD_JOGGING] = "jogging",
  	[IIO_MOD_WALKING] = "walking",
  	[IIO_MOD_STILL] = "still",
5a1a93298   Irina Tirdea   iio: core: Introd...
119
  	[IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z] = "sqrt(x^2+y^2+z^2)",
1ce87f21e   Lars-Peter Clausen   iio: Add I/Q modi...
120
121
  	[IIO_MOD_I] = "i",
  	[IIO_MOD_Q] = "q",
8ff6b3bc9   Matt Ranostay   iio: chemical: Ad...
122
123
  	[IIO_MOD_CO2] = "co2",
  	[IIO_MOD_VOC] = "voc",
17abc9ec6   Tomasz Duszynski   iio: add IIO_MASS...
124
125
126
127
  	[IIO_MOD_PM1] = "pm1",
  	[IIO_MOD_PM2P5] = "pm2p5",
  	[IIO_MOD_PM4] = "pm4",
  	[IIO_MOD_PM10] = "pm10",
1d892719e   Jonathan Cameron   staging:iio: allo...
128
129
130
131
  };
  
  /* relies on pairs of these shared then separate */
  static const char * const iio_chan_info_postfix[] = {
75a973c75   Jonathan Cameron   staging:iio: Make...
132
133
  	[IIO_CHAN_INFO_RAW] = "raw",
  	[IIO_CHAN_INFO_PROCESSED] = "input",
c8a9f8056   Jonathan Cameron   staging:iio:treew...
134
135
136
137
138
139
140
141
  	[IIO_CHAN_INFO_SCALE] = "scale",
  	[IIO_CHAN_INFO_OFFSET] = "offset",
  	[IIO_CHAN_INFO_CALIBSCALE] = "calibscale",
  	[IIO_CHAN_INFO_CALIBBIAS] = "calibbias",
  	[IIO_CHAN_INFO_PEAK] = "peak_raw",
  	[IIO_CHAN_INFO_PEAK_SCALE] = "peak_scale",
  	[IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW] = "quadrature_correction_raw",
  	[IIO_CHAN_INFO_AVERAGE_RAW] = "mean_raw",
df94aba81   Jonathan Cameron   staging:iio: filt...
142
143
  	[IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY]
  	= "filter_low_pass_3db_frequency",
3f7f642b9   Martin Fuzzey   iio: core: add hi...
144
145
  	[IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY]
  	= "filter_high_pass_3db_frequency",
ce85a1cbc   Laxman Dewangan   staging: iio: add...
146
  	[IIO_CHAN_INFO_SAMP_FREQ] = "sampling_frequency",
a6b12855b   Michael Hennerich   iio: core: Introd...
147
148
  	[IIO_CHAN_INFO_FREQUENCY] = "frequency",
  	[IIO_CHAN_INFO_PHASE] = "phase",
b65d62122   Michael Hennerich   iio: core: introd...
149
  	[IIO_CHAN_INFO_HARDWAREGAIN] = "hardwaregain",
7c9ab035a   srinivas pandruvada   iio: core: Add hy...
150
  	[IIO_CHAN_INFO_HYSTERESIS] = "hysteresis",
899d90bdf   Peter Meerwald   iio: Add INT_TIME...
151
  	[IIO_CHAN_INFO_INT_TIME] = "integration_time",
a88bfe785   Irina Tirdea   iio: core: Introd...
152
  	[IIO_CHAN_INFO_ENABLE] = "en",
bcdf28fb1   Irina Tirdea   iio: core: Introd...
153
  	[IIO_CHAN_INFO_CALIBHEIGHT] = "calibheight",
d37f6836f   Irina Tirdea   iio: core: Introd...
154
  	[IIO_CHAN_INFO_CALIBWEIGHT] = "calibweight",
2f0ecb7c6   Irina Tirdea   iio: core: Introd...
155
156
  	[IIO_CHAN_INFO_DEBOUNCE_COUNT] = "debounce_count",
  	[IIO_CHAN_INFO_DEBOUNCE_TIME] = "debounce_time",
c8a858543   Vianney le ClĂ©ment de Saint-Marcq   iio: core: Introd...
157
  	[IIO_CHAN_INFO_CALIBEMISSIVITY] = "calibemissivity",
faaa44955   Irina Tirdea   iio: core: Introd...
158
  	[IIO_CHAN_INFO_OVERSAMPLING_RATIO] = "oversampling_ratio",
1d892719e   Jonathan Cameron   staging:iio: allo...
159
  };
a7e57dce0   Sachin Kamat   iio: core: Move k...
160
161
162
163
164
  /**
   * iio_find_channel_from_si() - get channel from its scan index
   * @indio_dev:		device
   * @si:			scan index to match
   */
5fb21c824   Jonathan Cameron   staging:iio:find ...
165
166
167
168
169
170
171
172
173
174
  const struct iio_chan_spec
  *iio_find_channel_from_si(struct iio_dev *indio_dev, int si)
  {
  	int i;
  
  	for (i = 0; i < indio_dev->num_channels; i++)
  		if (indio_dev->channels[i].scan_index == si)
  			return &indio_dev->channels[i];
  	return NULL;
  }
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
175
176
177
178
179
180
181
182
183
  /* This turns up an awful lot */
  ssize_t iio_read_const_attr(struct device *dev,
  			    struct device_attribute *attr,
  			    char *buf)
  {
  	return sprintf(buf, "%s
  ", to_iio_const_attr(attr)->string);
  }
  EXPORT_SYMBOL(iio_read_const_attr);
bc2b7dab6   Gregor Boirie   iio:core: timesta...
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
  static int iio_device_set_clock(struct iio_dev *indio_dev, clockid_t clock_id)
  {
  	int ret;
  	const struct iio_event_interface *ev_int = indio_dev->event_interface;
  
  	ret = mutex_lock_interruptible(&indio_dev->mlock);
  	if (ret)
  		return ret;
  	if ((ev_int && iio_event_enabled(ev_int)) ||
  	    iio_buffer_enabled(indio_dev)) {
  		mutex_unlock(&indio_dev->mlock);
  		return -EBUSY;
  	}
  	indio_dev->clock_id = clock_id;
  	mutex_unlock(&indio_dev->mlock);
  
  	return 0;
  }
  
  /**
   * iio_get_time_ns() - utility function to get a time stamp for events etc
   * @indio_dev: device
   */
  s64 iio_get_time_ns(const struct iio_dev *indio_dev)
  {
45e7f5d28   Arnd Bergmann   iio: use timespec...
209
  	struct timespec64 tp;
bc2b7dab6   Gregor Boirie   iio:core: timesta...
210
211
212
  
  	switch (iio_device_get_clock(indio_dev)) {
  	case CLOCK_REALTIME:
45e7f5d28   Arnd Bergmann   iio: use timespec...
213
  		return ktime_get_real_ns();
bc2b7dab6   Gregor Boirie   iio:core: timesta...
214
  	case CLOCK_MONOTONIC:
45e7f5d28   Arnd Bergmann   iio: use timespec...
215
  		return ktime_get_ns();
bc2b7dab6   Gregor Boirie   iio:core: timesta...
216
  	case CLOCK_MONOTONIC_RAW:
45e7f5d28   Arnd Bergmann   iio: use timespec...
217
  		return ktime_get_raw_ns();
bc2b7dab6   Gregor Boirie   iio:core: timesta...
218
  	case CLOCK_REALTIME_COARSE:
45e7f5d28   Arnd Bergmann   iio: use timespec...
219
  		return ktime_to_ns(ktime_get_coarse_real());
bc2b7dab6   Gregor Boirie   iio:core: timesta...
220
  	case CLOCK_MONOTONIC_COARSE:
45e7f5d28   Arnd Bergmann   iio: use timespec...
221
222
  		ktime_get_coarse_ts64(&tp);
  		return timespec64_to_ns(&tp);
bc2b7dab6   Gregor Boirie   iio:core: timesta...
223
  	case CLOCK_BOOTTIME:
9285ec4c8   Jason A. Donenfeld   timekeeping: Use ...
224
  		return ktime_get_boottime_ns();
bc2b7dab6   Gregor Boirie   iio:core: timesta...
225
  	case CLOCK_TAI:
9285ec4c8   Jason A. Donenfeld   timekeeping: Use ...
226
  		return ktime_get_clocktai_ns();
bc2b7dab6   Gregor Boirie   iio:core: timesta...
227
228
229
  	default:
  		BUG();
  	}
bc2b7dab6   Gregor Boirie   iio:core: timesta...
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
  }
  EXPORT_SYMBOL(iio_get_time_ns);
  
  /**
   * iio_get_time_res() - utility function to get time stamp clock resolution in
   *                      nano seconds.
   * @indio_dev: device
   */
  unsigned int iio_get_time_res(const struct iio_dev *indio_dev)
  {
  	switch (iio_device_get_clock(indio_dev)) {
  	case CLOCK_REALTIME:
  	case CLOCK_MONOTONIC:
  	case CLOCK_MONOTONIC_RAW:
  	case CLOCK_BOOTTIME:
  	case CLOCK_TAI:
  		return hrtimer_resolution;
  	case CLOCK_REALTIME_COARSE:
  	case CLOCK_MONOTONIC_COARSE:
  		return LOW_RES_NSEC;
  	default:
  		BUG();
  	}
  }
  EXPORT_SYMBOL(iio_get_time_res);
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
255
256
257
  static int __init iio_init(void)
  {
  	int ret;
5aaaeba82   Jonathan Cameron   staging: iio: Mov...
258
259
  	/* Register sysfs bus */
  	ret  = bus_register(&iio_bus_type);
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
260
  	if (ret < 0) {
3176dd5d3   Sachin Kamat   iio: core: Use pr...
261
262
  		pr_err("could not register bus type
  ");
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
263
264
  		goto error_nothing;
  	}
9aa1a167f   Jonathan Cameron   staging:iio:core ...
265
266
  	ret = alloc_chrdev_region(&iio_devt, 0, IIO_DEV_MAX, "iio");
  	if (ret < 0) {
3176dd5d3   Sachin Kamat   iio: core: Use pr...
267
268
  		pr_err("failed to allocate char dev region
  ");
5aaaeba82   Jonathan Cameron   staging: iio: Mov...
269
  		goto error_unregister_bus_type;
9aa1a167f   Jonathan Cameron   staging:iio:core ...
270
  	}
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
271

e553f182d   Michael Hennerich   staging: iio: cor...
272
  	iio_debugfs_dentry = debugfs_create_dir("iio", NULL);
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
273
  	return 0;
5aaaeba82   Jonathan Cameron   staging: iio: Mov...
274
275
  error_unregister_bus_type:
  	bus_unregister(&iio_bus_type);
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
276
277
278
279
280
281
  error_nothing:
  	return ret;
  }
  
  static void __exit iio_exit(void)
  {
9aa1a167f   Jonathan Cameron   staging:iio:core ...
282
283
  	if (iio_devt)
  		unregister_chrdev_region(iio_devt, IIO_DEV_MAX);
5aaaeba82   Jonathan Cameron   staging: iio: Mov...
284
  	bus_unregister(&iio_bus_type);
e553f182d   Michael Hennerich   staging: iio: cor...
285
286
287
288
  	debugfs_remove(iio_debugfs_dentry);
  }
  
  #if defined(CONFIG_DEBUG_FS)
e553f182d   Michael Hennerich   staging: iio: cor...
289
290
291
292
293
294
295
296
297
298
299
300
  static ssize_t iio_debugfs_read_reg(struct file *file, char __user *userbuf,
  			      size_t count, loff_t *ppos)
  {
  	struct iio_dev *indio_dev = file->private_data;
  	char buf[20];
  	unsigned val = 0;
  	ssize_t len;
  	int ret;
  
  	ret = indio_dev->info->debugfs_reg_access(indio_dev,
  						  indio_dev->cached_reg_addr,
  						  0, &val);
3d62c78a6   Matt Fornero   iio: core: Return...
301
  	if (ret) {
e553f182d   Michael Hennerich   staging: iio: cor...
302
303
  		dev_err(indio_dev->dev.parent, "%s: read failed
  ", __func__);
3d62c78a6   Matt Fornero   iio: core: Return...
304
305
  		return ret;
  	}
e553f182d   Michael Hennerich   staging: iio: cor...
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
  
  	len = snprintf(buf, sizeof(buf), "0x%X
  ", val);
  
  	return simple_read_from_buffer(userbuf, count, ppos, buf, len);
  }
  
  static ssize_t iio_debugfs_write_reg(struct file *file,
  		     const char __user *userbuf, size_t count, loff_t *ppos)
  {
  	struct iio_dev *indio_dev = file->private_data;
  	unsigned reg, val;
  	char buf[80];
  	int ret;
  
  	count = min_t(size_t, count, (sizeof(buf)-1));
  	if (copy_from_user(buf, userbuf, count))
  		return -EFAULT;
  
  	buf[count] = 0;
  
  	ret = sscanf(buf, "%i %i", &reg, &val);
  
  	switch (ret) {
  	case 1:
  		indio_dev->cached_reg_addr = reg;
  		break;
  	case 2:
  		indio_dev->cached_reg_addr = reg;
  		ret = indio_dev->info->debugfs_reg_access(indio_dev, reg,
  							  val, NULL);
  		if (ret) {
  			dev_err(indio_dev->dev.parent, "%s: write failed
  ",
  				__func__);
  			return ret;
  		}
  		break;
  	default:
  		return -EINVAL;
  	}
  
  	return count;
  }
  
  static const struct file_operations iio_debugfs_reg_fops = {
5a28c8739   Axel Lin   IIO: industrialio...
352
  	.open = simple_open,
e553f182d   Michael Hennerich   staging: iio: cor...
353
354
355
356
357
358
359
  	.read = iio_debugfs_read_reg,
  	.write = iio_debugfs_write_reg,
  };
  
  static void iio_device_unregister_debugfs(struct iio_dev *indio_dev)
  {
  	debugfs_remove_recursive(indio_dev->debugfs_dentry);
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
360
  }
8915aacac   Greg Kroah-Hartman   iio: core: no nee...
361
  static void iio_device_register_debugfs(struct iio_dev *indio_dev)
e553f182d   Michael Hennerich   staging: iio: cor...
362
  {
e553f182d   Michael Hennerich   staging: iio: cor...
363
  	if (indio_dev->info->debugfs_reg_access == NULL)
8915aacac   Greg Kroah-Hartman   iio: core: no nee...
364
  		return;
e553f182d   Michael Hennerich   staging: iio: cor...
365

abd5a2fb3   Axel Lin   IIO: industrialio...
366
  	if (!iio_debugfs_dentry)
8915aacac   Greg Kroah-Hartman   iio: core: no nee...
367
  		return;
e553f182d   Michael Hennerich   staging: iio: cor...
368
369
370
371
  
  	indio_dev->debugfs_dentry =
  		debugfs_create_dir(dev_name(&indio_dev->dev),
  				   iio_debugfs_dentry);
e553f182d   Michael Hennerich   staging: iio: cor...
372

8915aacac   Greg Kroah-Hartman   iio: core: no nee...
373
374
375
  	debugfs_create_file("direct_reg_access", 0644,
  			    indio_dev->debugfs_dentry, indio_dev,
  			    &iio_debugfs_reg_fops);
e553f182d   Michael Hennerich   staging: iio: cor...
376
377
  }
  #else
8915aacac   Greg Kroah-Hartman   iio: core: no nee...
378
  static void iio_device_register_debugfs(struct iio_dev *indio_dev)
e553f182d   Michael Hennerich   staging: iio: cor...
379
  {
e553f182d   Michael Hennerich   staging: iio: cor...
380
381
382
383
384
385
  }
  
  static void iio_device_unregister_debugfs(struct iio_dev *indio_dev)
  {
  }
  #endif /* CONFIG_DEBUG_FS */
4fee7e168   Lars-Peter Clausen   staging:iio: Fix ...
386
387
388
389
  static ssize_t iio_read_channel_ext_info(struct device *dev,
  				     struct device_attribute *attr,
  				     char *buf)
  {
e53f5ac52   Lars-Peter Clausen   iio: Use dev_to_i...
390
  	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
4fee7e168   Lars-Peter Clausen   staging:iio: Fix ...
391
392
393
394
  	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
  	const struct iio_chan_spec_ext_info *ext_info;
  
  	ext_info = &this_attr->c->ext_info[this_attr->address];
fc6d11398   Michael Hennerich   iio: core: iio_ch...
395
  	return ext_info->read(indio_dev, ext_info->private, this_attr->c, buf);
4fee7e168   Lars-Peter Clausen   staging:iio: Fix ...
396
397
398
399
400
401
402
  }
  
  static ssize_t iio_write_channel_ext_info(struct device *dev,
  				     struct device_attribute *attr,
  				     const char *buf,
  					 size_t len)
  {
e53f5ac52   Lars-Peter Clausen   iio: Use dev_to_i...
403
  	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
4fee7e168   Lars-Peter Clausen   staging:iio: Fix ...
404
405
406
407
  	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
  	const struct iio_chan_spec_ext_info *ext_info;
  
  	ext_info = &this_attr->c->ext_info[this_attr->address];
fc6d11398   Michael Hennerich   iio: core: iio_ch...
408
409
  	return ext_info->write(indio_dev, ext_info->private,
  			       this_attr->c, buf, len);
4fee7e168   Lars-Peter Clausen   staging:iio: Fix ...
410
  }
5212cc8a9   Lars-Peter Clausen   iio: Add helper f...
411
412
413
414
415
416
417
418
419
420
421
  ssize_t iio_enum_available_read(struct iio_dev *indio_dev,
  	uintptr_t priv, const struct iio_chan_spec *chan, char *buf)
  {
  	const struct iio_enum *e = (const struct iio_enum *)priv;
  	unsigned int i;
  	size_t len = 0;
  
  	if (!e->num_items)
  		return 0;
  
  	for (i = 0; i < e->num_items; ++i)
74dcd439b   Lars-Peter Clausen   iio: iio_enum_ava...
422
  		len += scnprintf(buf + len, PAGE_SIZE - len, "%s ", e->items[i]);
5212cc8a9   Lars-Peter Clausen   iio: Add helper f...
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
  
  	/* replace last space with a newline */
  	buf[len - 1] = '
  ';
  
  	return len;
  }
  EXPORT_SYMBOL_GPL(iio_enum_available_read);
  
  ssize_t iio_enum_read(struct iio_dev *indio_dev,
  	uintptr_t priv, const struct iio_chan_spec *chan, char *buf)
  {
  	const struct iio_enum *e = (const struct iio_enum *)priv;
  	int i;
  
  	if (!e->get)
  		return -EINVAL;
  
  	i = e->get(indio_dev, chan);
  	if (i < 0)
  		return i;
  	else if (i >= e->num_items)
  		return -EINVAL;
598db5816   Kees Cook   iio: force snprin...
446
447
  	return snprintf(buf, PAGE_SIZE, "%s
  ", e->items[i]);
5212cc8a9   Lars-Peter Clausen   iio: Add helper f...
448
449
450
451
452
453
454
455
  }
  EXPORT_SYMBOL_GPL(iio_enum_read);
  
  ssize_t iio_enum_write(struct iio_dev *indio_dev,
  	uintptr_t priv, const struct iio_chan_spec *chan, const char *buf,
  	size_t len)
  {
  	const struct iio_enum *e = (const struct iio_enum *)priv;
5212cc8a9   Lars-Peter Clausen   iio: Add helper f...
456
457
458
459
  	int ret;
  
  	if (!e->set)
  		return -EINVAL;
02e9a0ff0   Andy Shevchenko   iio: core: Use __...
460
461
462
  	ret = __sysfs_match_string(e->items, e->num_items, buf);
  	if (ret < 0)
  		return ret;
5212cc8a9   Lars-Peter Clausen   iio: Add helper f...
463

02e9a0ff0   Andy Shevchenko   iio: core: Use __...
464
  	ret = e->set(indio_dev, chan, ret);
5212cc8a9   Lars-Peter Clausen   iio: Add helper f...
465
466
467
  	return ret ? ret : len;
  }
  EXPORT_SYMBOL_GPL(iio_enum_write);
dfc57732a   Gregor Boirie   iio:core: mountin...
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
  static const struct iio_mount_matrix iio_mount_idmatrix = {
  	.rotation = {
  		"1", "0", "0",
  		"0", "1", "0",
  		"0", "0", "1"
  	}
  };
  
  static int iio_setup_mount_idmatrix(const struct device *dev,
  				    struct iio_mount_matrix *matrix)
  {
  	*matrix = iio_mount_idmatrix;
  	dev_info(dev, "mounting matrix not found: using identity...
  ");
  	return 0;
  }
  
  ssize_t iio_show_mount_matrix(struct iio_dev *indio_dev, uintptr_t priv,
  			      const struct iio_chan_spec *chan, char *buf)
  {
  	const struct iio_mount_matrix *mtx = ((iio_get_mount_matrix_t *)
  					      priv)(indio_dev, chan);
  
  	if (IS_ERR(mtx))
  		return PTR_ERR(mtx);
  
  	if (!mtx)
  		mtx = &iio_mount_idmatrix;
  
  	return snprintf(buf, PAGE_SIZE, "%s, %s, %s; %s, %s, %s; %s, %s, %s
  ",
  			mtx->rotation[0], mtx->rotation[1], mtx->rotation[2],
  			mtx->rotation[3], mtx->rotation[4], mtx->rotation[5],
  			mtx->rotation[6], mtx->rotation[7], mtx->rotation[8]);
  }
  EXPORT_SYMBOL_GPL(iio_show_mount_matrix);
  
  /**
fb1589710   Andy Shevchenko   iio: Allow to rea...
506
507
   * iio_read_mount_matrix() - retrieve iio device mounting matrix from
   *                           device "mount-matrix" property
dfc57732a   Gregor Boirie   iio:core: mountin...
508
509
510
511
512
513
514
515
516
   * @dev:	device the mounting matrix property is assigned to
   * @propname:	device specific mounting matrix property name
   * @matrix:	where to store retrieved matrix
   *
   * If device is assigned no mounting matrix property, a default 3x3 identity
   * matrix will be filled in.
   *
   * Return: 0 if success, or a negative error code on failure.
   */
fb1589710   Andy Shevchenko   iio: Allow to rea...
517
518
  int iio_read_mount_matrix(struct device *dev, const char *propname,
  			  struct iio_mount_matrix *matrix)
dfc57732a   Gregor Boirie   iio:core: mountin...
519
  {
fb1589710   Andy Shevchenko   iio: Allow to rea...
520
521
  	size_t len = ARRAY_SIZE(iio_mount_idmatrix.rotation);
  	int err;
dfc57732a   Gregor Boirie   iio:core: mountin...
522

fb1589710   Andy Shevchenko   iio: Allow to rea...
523
524
525
526
  	err = device_property_read_string_array(dev, propname,
  						matrix->rotation, len);
  	if (err == len)
  		return 0;
dfc57732a   Gregor Boirie   iio:core: mountin...
527

fb1589710   Andy Shevchenko   iio: Allow to rea...
528
529
530
  	if (err >= 0)
  		/* Invalid number of matrix entries. */
  		return -EINVAL;
dfc57732a   Gregor Boirie   iio:core: mountin...
531

fb1589710   Andy Shevchenko   iio: Allow to rea...
532
533
534
  	if (err != -EINVAL)
  		/* Invalid matrix declaration format. */
  		return err;
dfc57732a   Gregor Boirie   iio:core: mountin...
535
536
537
538
  
  	/* Matrix was not declared at all: fallback to identity. */
  	return iio_setup_mount_idmatrix(dev, matrix);
  }
fb1589710   Andy Shevchenko   iio: Allow to rea...
539
  EXPORT_SYMBOL(iio_read_mount_matrix);
dfc57732a   Gregor Boirie   iio:core: mountin...
540

512396000   Jonathan Cameron   iio:core: add a c...
541
542
  static ssize_t __iio_format_value(char *buf, size_t len, unsigned int type,
  				  int size, const int *vals)
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
543
  {
7985e7c10   Lars-Peter Clausen   iio: Introduce a ...
544
  	unsigned long long tmp;
512396000   Jonathan Cameron   iio:core: add a c...
545
  	int tmp0, tmp1;
67eedba39   Michael Hennerich   iio: core: introd...
546
  	bool scale_db = false;
1d892719e   Jonathan Cameron   staging:iio: allo...
547

3661f3f5e   Lars-Peter Clausen   iio: Factor IIO v...
548
  	switch (type) {
67eedba39   Michael Hennerich   iio: core: introd...
549
  	case IIO_VAL_INT:
512396000   Jonathan Cameron   iio:core: add a c...
550
  		return snprintf(buf, len, "%d", vals[0]);
67eedba39   Michael Hennerich   iio: core: introd...
551
552
  	case IIO_VAL_INT_PLUS_MICRO_DB:
  		scale_db = true;
9d793c1a7   Gustavo A. R. Silva   iio: core: Mark e...
553
  		/* fall through */
67eedba39   Michael Hennerich   iio: core: introd...
554
  	case IIO_VAL_INT_PLUS_MICRO:
9fbfb4b37   Srinivas Pandruvada   IIO: core: Introd...
555
  		if (vals[1] < 0)
512396000   Jonathan Cameron   iio:core: add a c...
556
557
  			return snprintf(buf, len, "-%d.%06u%s", abs(vals[0]),
  					-vals[1], scale_db ? " dB" : "");
1d892719e   Jonathan Cameron   staging:iio: allo...
558
  		else
512396000   Jonathan Cameron   iio:core: add a c...
559
560
  			return snprintf(buf, len, "%d.%06u%s", vals[0], vals[1],
  					scale_db ? " dB" : "");
67eedba39   Michael Hennerich   iio: core: introd...
561
  	case IIO_VAL_INT_PLUS_NANO:
9fbfb4b37   Srinivas Pandruvada   IIO: core: Introd...
562
  		if (vals[1] < 0)
512396000   Jonathan Cameron   iio:core: add a c...
563
564
  			return snprintf(buf, len, "-%d.%09u", abs(vals[0]),
  					-vals[1]);
71646e2c7   Michael Hennerich   iio: industrialio...
565
  		else
512396000   Jonathan Cameron   iio:core: add a c...
566
  			return snprintf(buf, len, "%d.%09u", vals[0], vals[1]);
7985e7c10   Lars-Peter Clausen   iio: Introduce a ...
567
  	case IIO_VAL_FRACTIONAL:
9fbfb4b37   Srinivas Pandruvada   IIO: core: Introd...
568
  		tmp = div_s64((s64)vals[0] * 1000000000LL, vals[1]);
512396000   Jonathan Cameron   iio:core: add a c...
569
570
571
  		tmp1 = vals[1];
  		tmp0 = (int)div_s64_rem(tmp, 1000000000, &tmp1);
  		return snprintf(buf, len, "%d.%09u", tmp0, abs(tmp1));
103d9fb90   Lars-Peter Clausen   iio: Add a logari...
572
  	case IIO_VAL_FRACTIONAL_LOG2:
7fd6592d1   Nikolaus Schulz   iio: core: Fix II...
573
574
575
  		tmp = shift_right((s64)vals[0] * 1000000000LL, vals[1]);
  		tmp0 = (int)div_s64_rem(tmp, 1000000000LL, &tmp1);
  		return snprintf(buf, len, "%d.%09u", tmp0, abs(tmp1));
9fbfb4b37   Srinivas Pandruvada   IIO: core: Introd...
576
577
578
  	case IIO_VAL_INT_MULTIPLE:
  	{
  		int i;
512396000   Jonathan Cameron   iio:core: add a c...
579
  		int l = 0;
9fbfb4b37   Srinivas Pandruvada   IIO: core: Introd...
580

512396000   Jonathan Cameron   iio:core: add a c...
581
582
583
584
585
586
  		for (i = 0; i < size; ++i) {
  			l += snprintf(&buf[l], len - l, "%d ", vals[i]);
  			if (l >= len)
  				break;
  		}
  		return l;
9fbfb4b37   Srinivas Pandruvada   IIO: core: Introd...
587
  	}
67eedba39   Michael Hennerich   iio: core: introd...
588
  	default:
1d892719e   Jonathan Cameron   staging:iio: allo...
589
  		return 0;
67eedba39   Michael Hennerich   iio: core: introd...
590
  	}
1d892719e   Jonathan Cameron   staging:iio: allo...
591
  }
512396000   Jonathan Cameron   iio:core: add a c...
592
593
594
595
596
  
  /**
   * iio_format_value() - Formats a IIO value into its string representation
   * @buf:	The buffer to which the formatted value gets written
   *		which is assumed to be big enough (i.e. PAGE_SIZE).
c175cb7cd   Randy Dunlap   iio: fix kernel-d...
597
   * @type:	One of the IIO_VAL_* constants. This decides how the val
512396000   Jonathan Cameron   iio:core: add a c...
598
599
600
601
602
603
604
   *		and val2 parameters are formatted.
   * @size:	Number of IIO value entries contained in vals
   * @vals:	Pointer to the values, exact meaning depends on the
   *		type parameter.
   *
   * Return: 0 by default, a negative number on failure or the
   *	   total number of characters written for a type that belongs
c175cb7cd   Randy Dunlap   iio: fix kernel-d...
605
   *	   to the IIO_VAL_* constant.
512396000   Jonathan Cameron   iio:core: add a c...
606
607
608
609
610
611
612
613
614
615
616
617
   */
  ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals)
  {
  	ssize_t len;
  
  	len = __iio_format_value(buf, PAGE_SIZE, type, size, vals);
  	if (len >= PAGE_SIZE - 1)
  		return -EFBIG;
  
  	return len + sprintf(buf + len, "
  ");
  }
7d2c2acac   Andrew F. Davis   iio: Make IIO val...
618
  EXPORT_SYMBOL_GPL(iio_format_value);
1d892719e   Jonathan Cameron   staging:iio: allo...
619

3661f3f5e   Lars-Peter Clausen   iio: Factor IIO v...
620
621
622
623
624
625
  static ssize_t iio_read_channel_info(struct device *dev,
  				     struct device_attribute *attr,
  				     char *buf)
  {
  	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
  	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
9fbfb4b37   Srinivas Pandruvada   IIO: core: Introd...
626
627
628
629
630
631
632
633
634
635
636
637
  	int vals[INDIO_MAX_RAW_ELEMENTS];
  	int ret;
  	int val_len = 2;
  
  	if (indio_dev->info->read_raw_multi)
  		ret = indio_dev->info->read_raw_multi(indio_dev, this_attr->c,
  							INDIO_MAX_RAW_ELEMENTS,
  							vals, &val_len,
  							this_attr->address);
  	else
  		ret = indio_dev->info->read_raw(indio_dev, this_attr->c,
  				    &vals[0], &vals[1], this_attr->address);
3661f3f5e   Lars-Peter Clausen   iio: Factor IIO v...
638
639
640
  
  	if (ret < 0)
  		return ret;
9fbfb4b37   Srinivas Pandruvada   IIO: core: Introd...
641
  	return iio_format_value(buf, ret, val_len, vals);
3661f3f5e   Lars-Peter Clausen   iio: Factor IIO v...
642
  }
512396000   Jonathan Cameron   iio:core: add a c...
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
  static ssize_t iio_format_avail_list(char *buf, const int *vals,
  				     int type, int length)
  {
  	int i;
  	ssize_t len = 0;
  
  	switch (type) {
  	case IIO_VAL_INT:
  		for (i = 0; i < length; i++) {
  			len += __iio_format_value(buf + len, PAGE_SIZE - len,
  						  type, 1, &vals[i]);
  			if (len >= PAGE_SIZE)
  				return -EFBIG;
  			if (i < length - 1)
  				len += snprintf(buf + len, PAGE_SIZE - len,
  						" ");
  			else
  				len += snprintf(buf + len, PAGE_SIZE - len,
  						"
  ");
  			if (len >= PAGE_SIZE)
  				return -EFBIG;
  		}
  		break;
  	default:
  		for (i = 0; i < length / 2; i++) {
  			len += __iio_format_value(buf + len, PAGE_SIZE - len,
  						  type, 2, &vals[i * 2]);
  			if (len >= PAGE_SIZE)
  				return -EFBIG;
  			if (i < length / 2 - 1)
  				len += snprintf(buf + len, PAGE_SIZE - len,
  						" ");
  			else
  				len += snprintf(buf + len, PAGE_SIZE - len,
  						"
  ");
  			if (len >= PAGE_SIZE)
  				return -EFBIG;
  		}
  	}
  
  	return len;
  }
  
  static ssize_t iio_format_avail_range(char *buf, const int *vals, int type)
  {
  	int i;
  	ssize_t len;
  
  	len = snprintf(buf, PAGE_SIZE, "[");
  	switch (type) {
  	case IIO_VAL_INT:
  		for (i = 0; i < 3; i++) {
  			len += __iio_format_value(buf + len, PAGE_SIZE - len,
  						  type, 1, &vals[i]);
  			if (len >= PAGE_SIZE)
  				return -EFBIG;
  			if (i < 2)
  				len += snprintf(buf + len, PAGE_SIZE - len,
  						" ");
  			else
  				len += snprintf(buf + len, PAGE_SIZE - len,
  						"]
  ");
  			if (len >= PAGE_SIZE)
  				return -EFBIG;
  		}
  		break;
  	default:
  		for (i = 0; i < 3; i++) {
  			len += __iio_format_value(buf + len, PAGE_SIZE - len,
  						  type, 2, &vals[i * 2]);
  			if (len >= PAGE_SIZE)
  				return -EFBIG;
  			if (i < 2)
  				len += snprintf(buf + len, PAGE_SIZE - len,
  						" ");
  			else
  				len += snprintf(buf + len, PAGE_SIZE - len,
  						"]
  ");
  			if (len >= PAGE_SIZE)
  				return -EFBIG;
  		}
  	}
  
  	return len;
  }
  
  static ssize_t iio_read_channel_info_avail(struct device *dev,
  					   struct device_attribute *attr,
  					   char *buf)
  {
  	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
  	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
  	const int *vals;
  	int ret;
  	int length;
  	int type;
  
  	ret = indio_dev->info->read_avail(indio_dev, this_attr->c,
  					  &vals, &type, &length,
  					  this_attr->address);
  
  	if (ret < 0)
  		return ret;
  	switch (ret) {
  	case IIO_AVAIL_LIST:
  		return iio_format_avail_list(buf, vals, type, length);
  	case IIO_AVAIL_RANGE:
  		return iio_format_avail_range(buf, vals, type);
  	default:
  		return -EINVAL;
  	}
  }
6807d7211   Lars-Peter Clausen   iio: Factor out f...
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
  /**
   * iio_str_to_fixpoint() - Parse a fixed-point number from a string
   * @str: The string to parse
   * @fract_mult: Multiplier for the first decimal place, should be a power of 10
   * @integer: The integer part of the number
   * @fract: The fractional part of the number
   *
   * Returns 0 on success, or a negative error code if the string could not be
   * parsed.
   */
  int iio_str_to_fixpoint(const char *str, int fract_mult,
  	int *integer, int *fract)
  {
  	int i = 0, f = 0;
  	bool integer_part = true, negative = false;
f47dff323   Sean Nyekjaer   iio: core: added ...
774
775
776
777
778
  	if (fract_mult == 0) {
  		*fract = 0;
  
  		return kstrtoint(str, 0, integer);
  	}
6807d7211   Lars-Peter Clausen   iio: Factor out f...
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
  	if (str[0] == '-') {
  		negative = true;
  		str++;
  	} else if (str[0] == '+') {
  		str++;
  	}
  
  	while (*str) {
  		if ('0' <= *str && *str <= '9') {
  			if (integer_part) {
  				i = i * 10 + *str - '0';
  			} else {
  				f += fract_mult * (*str - '0');
  				fract_mult /= 10;
  			}
  		} else if (*str == '
  ') {
  			if (*(str + 1) == '\0')
  				break;
  			else
  				return -EINVAL;
  		} else if (*str == '.' && integer_part) {
  			integer_part = false;
  		} else {
  			return -EINVAL;
  		}
  		str++;
  	}
  
  	if (negative) {
  		if (i)
  			i = -i;
  		else
  			f = -f;
  	}
  
  	*integer = i;
  	*fract = f;
  
  	return 0;
  }
  EXPORT_SYMBOL_GPL(iio_str_to_fixpoint);
1d892719e   Jonathan Cameron   staging:iio: allo...
821
822
823
824
825
  static ssize_t iio_write_channel_info(struct device *dev,
  				      struct device_attribute *attr,
  				      const char *buf,
  				      size_t len)
  {
e53f5ac52   Lars-Peter Clausen   iio: Use dev_to_i...
826
  	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
1d892719e   Jonathan Cameron   staging:iio: allo...
827
  	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
6807d7211   Lars-Peter Clausen   iio: Factor out f...
828
829
  	int ret, fract_mult = 100000;
  	int integer, fract;
1d892719e   Jonathan Cameron   staging:iio: allo...
830
831
  
  	/* Assumes decimal - precision based on number of digits */
6fe8135fc   Jonathan Cameron   staging:iio: impl...
832
  	if (!indio_dev->info->write_raw)
1d892719e   Jonathan Cameron   staging:iio: allo...
833
  		return -EINVAL;
5c04af048   Michael Hennerich   iio: industrialio...
834
835
836
837
  
  	if (indio_dev->info->write_raw_get_fmt)
  		switch (indio_dev->info->write_raw_get_fmt(indio_dev,
  			this_attr->c, this_attr->address)) {
f47dff323   Sean Nyekjaer   iio: core: added ...
838
839
840
  		case IIO_VAL_INT:
  			fract_mult = 0;
  			break;
5c04af048   Michael Hennerich   iio: industrialio...
841
842
843
844
845
846
847
848
849
  		case IIO_VAL_INT_PLUS_MICRO:
  			fract_mult = 100000;
  			break;
  		case IIO_VAL_INT_PLUS_NANO:
  			fract_mult = 100000000;
  			break;
  		default:
  			return -EINVAL;
  		}
6807d7211   Lars-Peter Clausen   iio: Factor out f...
850
851
852
  	ret = iio_str_to_fixpoint(buf, fract_mult, &integer, &fract);
  	if (ret)
  		return ret;
1d892719e   Jonathan Cameron   staging:iio: allo...
853

6fe8135fc   Jonathan Cameron   staging:iio: impl...
854
  	ret = indio_dev->info->write_raw(indio_dev, this_attr->c,
5c04af048   Michael Hennerich   iio: industrialio...
855
  					 integer, fract, this_attr->address);
1d892719e   Jonathan Cameron   staging:iio: allo...
856
857
858
859
860
  	if (ret)
  		return ret;
  
  	return len;
  }
df9c1c42c   Jonathan Cameron   staging:iio: Intr...
861
  static
1d892719e   Jonathan Cameron   staging:iio: allo...
862
863
864
865
866
867
868
869
870
871
  int __iio_device_attr_init(struct device_attribute *dev_attr,
  			   const char *postfix,
  			   struct iio_chan_spec const *chan,
  			   ssize_t (*readfunc)(struct device *dev,
  					       struct device_attribute *attr,
  					       char *buf),
  			   ssize_t (*writefunc)(struct device *dev,
  						struct device_attribute *attr,
  						const char *buf,
  						size_t len),
3704432fb   Jonathan Cameron   iio: refactor inf...
872
  			   enum iio_shared_by shared_by)
1d892719e   Jonathan Cameron   staging:iio: allo...
873
  {
3704432fb   Jonathan Cameron   iio: refactor inf...
874
  	int ret = 0;
7bbcf7e13   Lars-Peter Clausen   iio: Avoid unnece...
875
  	char *name = NULL;
3704432fb   Jonathan Cameron   iio: refactor inf...
876
  	char *full_postfix;
1d892719e   Jonathan Cameron   staging:iio: allo...
877
  	sysfs_attr_init(&dev_attr->attr);
1d892719e   Jonathan Cameron   staging:iio: allo...
878

ade7ef7ba   Jonathan Cameron   staging:iio: Diff...
879
  	/* Build up postfix of <extend_name>_<modifier>_postfix */
3704432fb   Jonathan Cameron   iio: refactor inf...
880
  	if (chan->modified && (shared_by == IIO_SEPARATE)) {
ade7ef7ba   Jonathan Cameron   staging:iio: Diff...
881
882
883
884
885
886
887
888
889
890
891
892
  		if (chan->extend_name)
  			full_postfix = kasprintf(GFP_KERNEL, "%s_%s_%s",
  						 iio_modifier_names[chan
  								    ->channel2],
  						 chan->extend_name,
  						 postfix);
  		else
  			full_postfix = kasprintf(GFP_KERNEL, "%s_%s",
  						 iio_modifier_names[chan
  								    ->channel2],
  						 postfix);
  	} else {
77bfa8baa   Lars-Peter Clausen   iio: Don't includ...
893
  		if (chan->extend_name == NULL || shared_by != IIO_SEPARATE)
ade7ef7ba   Jonathan Cameron   staging:iio: Diff...
894
895
896
897
898
899
900
  			full_postfix = kstrdup(postfix, GFP_KERNEL);
  		else
  			full_postfix = kasprintf(GFP_KERNEL,
  						 "%s_%s",
  						 chan->extend_name,
  						 postfix);
  	}
3704432fb   Jonathan Cameron   iio: refactor inf...
901
902
  	if (full_postfix == NULL)
  		return -ENOMEM;
1d892719e   Jonathan Cameron   staging:iio: allo...
903

4abf6f8b2   Justin P. Mattock   drivers:staging:i...
904
  	if (chan->differential) { /* Differential can not have modifier */
3704432fb   Jonathan Cameron   iio: refactor inf...
905
  		switch (shared_by) {
c006ec838   Jonathan Cameron   iio: add info_mas...
906
  		case IIO_SHARED_BY_ALL:
7bbcf7e13   Lars-Peter Clausen   iio: Avoid unnece...
907
  			name = kasprintf(GFP_KERNEL, "%s", full_postfix);
c006ec838   Jonathan Cameron   iio: add info_mas...
908
909
  			break;
  		case IIO_SHARED_BY_DIR:
7bbcf7e13   Lars-Peter Clausen   iio: Avoid unnece...
910
  			name = kasprintf(GFP_KERNEL, "%s_%s",
c006ec838   Jonathan Cameron   iio: add info_mas...
911
912
913
  						iio_direction[chan->output],
  						full_postfix);
  			break;
3704432fb   Jonathan Cameron   iio: refactor inf...
914
  		case IIO_SHARED_BY_TYPE:
7bbcf7e13   Lars-Peter Clausen   iio: Avoid unnece...
915
  			name = kasprintf(GFP_KERNEL, "%s_%s-%s_%s",
ade7ef7ba   Jonathan Cameron   staging:iio: Diff...
916
917
918
919
  					    iio_direction[chan->output],
  					    iio_chan_type_name_spec[chan->type],
  					    iio_chan_type_name_spec[chan->type],
  					    full_postfix);
3704432fb   Jonathan Cameron   iio: refactor inf...
920
921
922
  			break;
  		case IIO_SEPARATE:
  			if (!chan->indexed) {
231bfe53c   Dan Carpenter   iio: fix some war...
923
924
  				WARN(1, "Differential channels must be indexed
  ");
3704432fb   Jonathan Cameron   iio: refactor inf...
925
926
927
  				ret = -EINVAL;
  				goto error_free_full_postfix;
  			}
7bbcf7e13   Lars-Peter Clausen   iio: Avoid unnece...
928
  			name = kasprintf(GFP_KERNEL,
3704432fb   Jonathan Cameron   iio: refactor inf...
929
  					    "%s_%s%d-%s%d_%s",
ade7ef7ba   Jonathan Cameron   staging:iio: Diff...
930
931
932
933
934
935
  					    iio_direction[chan->output],
  					    iio_chan_type_name_spec[chan->type],
  					    chan->channel,
  					    iio_chan_type_name_spec[chan->type],
  					    chan->channel2,
  					    full_postfix);
3704432fb   Jonathan Cameron   iio: refactor inf...
936
  			break;
ade7ef7ba   Jonathan Cameron   staging:iio: Diff...
937
938
  		}
  	} else { /* Single ended */
3704432fb   Jonathan Cameron   iio: refactor inf...
939
  		switch (shared_by) {
c006ec838   Jonathan Cameron   iio: add info_mas...
940
  		case IIO_SHARED_BY_ALL:
7bbcf7e13   Lars-Peter Clausen   iio: Avoid unnece...
941
  			name = kasprintf(GFP_KERNEL, "%s", full_postfix);
c006ec838   Jonathan Cameron   iio: add info_mas...
942
943
  			break;
  		case IIO_SHARED_BY_DIR:
7bbcf7e13   Lars-Peter Clausen   iio: Avoid unnece...
944
  			name = kasprintf(GFP_KERNEL, "%s_%s",
c006ec838   Jonathan Cameron   iio: add info_mas...
945
946
947
  						iio_direction[chan->output],
  						full_postfix);
  			break;
3704432fb   Jonathan Cameron   iio: refactor inf...
948
  		case IIO_SHARED_BY_TYPE:
7bbcf7e13   Lars-Peter Clausen   iio: Avoid unnece...
949
  			name = kasprintf(GFP_KERNEL, "%s_%s_%s",
ade7ef7ba   Jonathan Cameron   staging:iio: Diff...
950
951
952
  					    iio_direction[chan->output],
  					    iio_chan_type_name_spec[chan->type],
  					    full_postfix);
3704432fb   Jonathan Cameron   iio: refactor inf...
953
954
955
956
  			break;
  
  		case IIO_SEPARATE:
  			if (chan->indexed)
7bbcf7e13   Lars-Peter Clausen   iio: Avoid unnece...
957
  				name = kasprintf(GFP_KERNEL, "%s_%s%d_%s",
3704432fb   Jonathan Cameron   iio: refactor inf...
958
959
960
961
962
  						    iio_direction[chan->output],
  						    iio_chan_type_name_spec[chan->type],
  						    chan->channel,
  						    full_postfix);
  			else
7bbcf7e13   Lars-Peter Clausen   iio: Avoid unnece...
963
  				name = kasprintf(GFP_KERNEL, "%s_%s_%s",
3704432fb   Jonathan Cameron   iio: refactor inf...
964
965
966
967
968
  						    iio_direction[chan->output],
  						    iio_chan_type_name_spec[chan->type],
  						    full_postfix);
  			break;
  		}
ade7ef7ba   Jonathan Cameron   staging:iio: Diff...
969
  	}
7bbcf7e13   Lars-Peter Clausen   iio: Avoid unnece...
970
  	if (name == NULL) {
1d892719e   Jonathan Cameron   staging:iio: allo...
971
972
973
  		ret = -ENOMEM;
  		goto error_free_full_postfix;
  	}
7bbcf7e13   Lars-Peter Clausen   iio: Avoid unnece...
974
  	dev_attr->attr.name = name;
1d892719e   Jonathan Cameron   staging:iio: allo...
975
976
977
978
979
980
981
982
983
984
  
  	if (readfunc) {
  		dev_attr->attr.mode |= S_IRUGO;
  		dev_attr->show = readfunc;
  	}
  
  	if (writefunc) {
  		dev_attr->attr.mode |= S_IWUSR;
  		dev_attr->store = writefunc;
  	}
7bbcf7e13   Lars-Peter Clausen   iio: Avoid unnece...
985

1d892719e   Jonathan Cameron   staging:iio: allo...
986
987
  error_free_full_postfix:
  	kfree(full_postfix);
3704432fb   Jonathan Cameron   iio: refactor inf...
988

1d892719e   Jonathan Cameron   staging:iio: allo...
989
990
  	return ret;
  }
df9c1c42c   Jonathan Cameron   staging:iio: Intr...
991
  static void __iio_device_attr_deinit(struct device_attribute *dev_attr)
1d892719e   Jonathan Cameron   staging:iio: allo...
992
993
994
995
996
  {
  	kfree(dev_attr->attr.name);
  }
  
  int __iio_add_chan_devattr(const char *postfix,
1d892719e   Jonathan Cameron   staging:iio: allo...
997
998
999
1000
1001
1002
1003
1004
  			   struct iio_chan_spec const *chan,
  			   ssize_t (*readfunc)(struct device *dev,
  					       struct device_attribute *attr,
  					       char *buf),
  			   ssize_t (*writefunc)(struct device *dev,
  						struct device_attribute *attr,
  						const char *buf,
  						size_t len),
e614a54b2   Jonathan Cameron   staging:iio:attrs...
1005
  			   u64 mask,
3704432fb   Jonathan Cameron   iio: refactor inf...
1006
  			   enum iio_shared_by shared_by,
1d892719e   Jonathan Cameron   staging:iio: allo...
1007
1008
1009
1010
1011
  			   struct device *dev,
  			   struct list_head *attr_list)
  {
  	int ret;
  	struct iio_dev_attr *iio_attr, *t;
670c11033   Sachin Kamat   iio: core: Add mi...
1012
  	iio_attr = kzalloc(sizeof(*iio_attr), GFP_KERNEL);
92825ff97   Hartmut Knaack   iio get rid of un...
1013
1014
  	if (iio_attr == NULL)
  		return -ENOMEM;
1d892719e   Jonathan Cameron   staging:iio: allo...
1015
1016
  	ret = __iio_device_attr_init(&iio_attr->dev_attr,
  				     postfix, chan,
3704432fb   Jonathan Cameron   iio: refactor inf...
1017
  				     readfunc, writefunc, shared_by);
1d892719e   Jonathan Cameron   staging:iio: allo...
1018
1019
1020
1021
1022
1023
1024
  	if (ret)
  		goto error_iio_dev_attr_free;
  	iio_attr->c = chan;
  	iio_attr->address = mask;
  	list_for_each_entry(t, attr_list, l)
  		if (strcmp(t->dev_attr.attr.name,
  			   iio_attr->dev_attr.attr.name) == 0) {
3704432fb   Jonathan Cameron   iio: refactor inf...
1025
  			if (shared_by == IIO_SEPARATE)
1d892719e   Jonathan Cameron   staging:iio: allo...
1026
1027
1028
1029
1030
1031
  				dev_err(dev, "tried to double register : %s
  ",
  					t->dev_attr.attr.name);
  			ret = -EBUSY;
  			goto error_device_attr_deinit;
  		}
1d892719e   Jonathan Cameron   staging:iio: allo...
1032
1033
1034
1035
1036
1037
1038
1039
  	list_add(&iio_attr->l, attr_list);
  
  	return 0;
  
  error_device_attr_deinit:
  	__iio_device_attr_deinit(&iio_attr->dev_attr);
  error_iio_dev_attr_free:
  	kfree(iio_attr);
1d892719e   Jonathan Cameron   staging:iio: allo...
1040
1041
  	return ret;
  }
3704432fb   Jonathan Cameron   iio: refactor inf...
1042
1043
1044
1045
  static int iio_device_add_info_mask_type(struct iio_dev *indio_dev,
  					 struct iio_chan_spec const *chan,
  					 enum iio_shared_by shared_by,
  					 const long *infomask)
1d892719e   Jonathan Cameron   staging:iio: allo...
1046
  {
3704432fb   Jonathan Cameron   iio: refactor inf...
1047
  	int i, ret, attrcount = 0;
1d892719e   Jonathan Cameron   staging:iio: allo...
1048

1016d5676   Orson Zhai   iio: core: Fix su...
1049
  	for_each_set_bit(i, infomask, sizeof(*infomask)*8) {
ef4b48565   Jonathan Cameron   iio:core: Fix bug...
1050
1051
  		if (i >= ARRAY_SIZE(iio_chan_info_postfix))
  			return -EINVAL;
8655cc490   Jonathan Cameron   iio: Add broken o...
1052
1053
1054
1055
1056
  		ret = __iio_add_chan_devattr(iio_chan_info_postfix[i],
  					     chan,
  					     &iio_read_channel_info,
  					     &iio_write_channel_info,
  					     i,
3704432fb   Jonathan Cameron   iio: refactor inf...
1057
  					     shared_by,
8655cc490   Jonathan Cameron   iio: Add broken o...
1058
1059
  					     &indio_dev->dev,
  					     &indio_dev->channel_attr_list);
3704432fb   Jonathan Cameron   iio: refactor inf...
1060
  		if ((ret == -EBUSY) && (shared_by != IIO_SEPARATE))
8655cc490   Jonathan Cameron   iio: Add broken o...
1061
  			continue;
3704432fb   Jonathan Cameron   iio: refactor inf...
1062
1063
  		else if (ret < 0)
  			return ret;
8655cc490   Jonathan Cameron   iio: Add broken o...
1064
1065
  		attrcount++;
  	}
5f420b420   Lars-Peter Clausen   staging:iio: Add ...
1066

3704432fb   Jonathan Cameron   iio: refactor inf...
1067
1068
  	return attrcount;
  }
512396000   Jonathan Cameron   iio:core: add a c...
1069
1070
1071
1072
1073
1074
1075
  static int iio_device_add_info_mask_type_avail(struct iio_dev *indio_dev,
  					       struct iio_chan_spec const *chan,
  					       enum iio_shared_by shared_by,
  					       const long *infomask)
  {
  	int i, ret, attrcount = 0;
  	char *avail_postfix;
1016d5676   Orson Zhai   iio: core: Fix su...
1076
  	for_each_set_bit(i, infomask, sizeof(*infomask) * 8) {
936d3e536   Young Xiao   iio:core: Fix bug...
1077
1078
  		if (i >= ARRAY_SIZE(iio_chan_info_postfix))
  			return -EINVAL;
512396000   Jonathan Cameron   iio:core: add a c...
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
  		avail_postfix = kasprintf(GFP_KERNEL,
  					  "%s_available",
  					  iio_chan_info_postfix[i]);
  		if (!avail_postfix)
  			return -ENOMEM;
  
  		ret = __iio_add_chan_devattr(avail_postfix,
  					     chan,
  					     &iio_read_channel_info_avail,
  					     NULL,
  					     i,
  					     shared_by,
  					     &indio_dev->dev,
  					     &indio_dev->channel_attr_list);
  		kfree(avail_postfix);
  		if ((ret == -EBUSY) && (shared_by != IIO_SEPARATE))
  			continue;
  		else if (ret < 0)
  			return ret;
  		attrcount++;
  	}
  
  	return attrcount;
  }
3704432fb   Jonathan Cameron   iio: refactor inf...
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
  static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
  					struct iio_chan_spec const *chan)
  {
  	int ret, attrcount = 0;
  	const struct iio_chan_spec_ext_info *ext_info;
  
  	if (chan->channel < 0)
  		return 0;
  	ret = iio_device_add_info_mask_type(indio_dev, chan,
  					    IIO_SEPARATE,
  					    &chan->info_mask_separate);
  	if (ret < 0)
  		return ret;
  	attrcount += ret;
512396000   Jonathan Cameron   iio:core: add a c...
1117
1118
1119
1120
1121
1122
1123
  	ret = iio_device_add_info_mask_type_avail(indio_dev, chan,
  						  IIO_SEPARATE,
  						  &chan->
  						  info_mask_separate_available);
  	if (ret < 0)
  		return ret;
  	attrcount += ret;
3704432fb   Jonathan Cameron   iio: refactor inf...
1124
1125
1126
1127
1128
1129
  	ret = iio_device_add_info_mask_type(indio_dev, chan,
  					    IIO_SHARED_BY_TYPE,
  					    &chan->info_mask_shared_by_type);
  	if (ret < 0)
  		return ret;
  	attrcount += ret;
512396000   Jonathan Cameron   iio:core: add a c...
1130
1131
1132
1133
1134
1135
1136
  	ret = iio_device_add_info_mask_type_avail(indio_dev, chan,
  						  IIO_SHARED_BY_TYPE,
  						  &chan->
  						  info_mask_shared_by_type_available);
  	if (ret < 0)
  		return ret;
  	attrcount += ret;
c006ec838   Jonathan Cameron   iio: add info_mas...
1137
1138
1139
1140
1141
1142
  	ret = iio_device_add_info_mask_type(indio_dev, chan,
  					    IIO_SHARED_BY_DIR,
  					    &chan->info_mask_shared_by_dir);
  	if (ret < 0)
  		return ret;
  	attrcount += ret;
512396000   Jonathan Cameron   iio:core: add a c...
1143
1144
1145
1146
1147
1148
  	ret = iio_device_add_info_mask_type_avail(indio_dev, chan,
  						  IIO_SHARED_BY_DIR,
  						  &chan->info_mask_shared_by_dir_available);
  	if (ret < 0)
  		return ret;
  	attrcount += ret;
c006ec838   Jonathan Cameron   iio: add info_mas...
1149
1150
1151
1152
1153
1154
  	ret = iio_device_add_info_mask_type(indio_dev, chan,
  					    IIO_SHARED_BY_ALL,
  					    &chan->info_mask_shared_by_all);
  	if (ret < 0)
  		return ret;
  	attrcount += ret;
512396000   Jonathan Cameron   iio:core: add a c...
1155
1156
1157
1158
1159
1160
  	ret = iio_device_add_info_mask_type_avail(indio_dev, chan,
  						  IIO_SHARED_BY_ALL,
  						  &chan->info_mask_shared_by_all_available);
  	if (ret < 0)
  		return ret;
  	attrcount += ret;
5f420b420   Lars-Peter Clausen   staging:iio: Add ...
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
  	if (chan->ext_info) {
  		unsigned int i = 0;
  		for (ext_info = chan->ext_info; ext_info->name; ext_info++) {
  			ret = __iio_add_chan_devattr(ext_info->name,
  					chan,
  					ext_info->read ?
  					    &iio_read_channel_ext_info : NULL,
  					ext_info->write ?
  					    &iio_write_channel_ext_info : NULL,
  					i,
  					ext_info->shared,
  					&indio_dev->dev,
  					&indio_dev->channel_attr_list);
  			i++;
  			if (ret == -EBUSY && ext_info->shared)
  				continue;
  
  			if (ret)
3704432fb   Jonathan Cameron   iio: refactor inf...
1179
  				return ret;
5f420b420   Lars-Peter Clausen   staging:iio: Add ...
1180
1181
1182
1183
  
  			attrcount++;
  		}
  	}
3704432fb   Jonathan Cameron   iio: refactor inf...
1184
  	return attrcount;
1d892719e   Jonathan Cameron   staging:iio: allo...
1185
  }
84088ebd1   Lars-Peter Clausen   iio: Add a helper...
1186
1187
1188
1189
1190
  /**
   * iio_free_chan_devattr_list() - Free a list of IIO device attributes
   * @attr_list: List of IIO device attributes
   *
   * This function frees the memory allocated for each of the IIO device
c1b03ab5e   Martin Fuzzey   iio: core: Fix do...
1191
   * attributes in the list.
84088ebd1   Lars-Peter Clausen   iio: Add a helper...
1192
1193
   */
  void iio_free_chan_devattr_list(struct list_head *attr_list)
1d892719e   Jonathan Cameron   staging:iio: allo...
1194
  {
84088ebd1   Lars-Peter Clausen   iio: Add a helper...
1195
1196
1197
1198
  	struct iio_dev_attr *p, *n;
  
  	list_for_each_entry_safe(p, n, attr_list, l) {
  		kfree(p->dev_attr.attr.name);
c1b03ab5e   Martin Fuzzey   iio: core: Fix do...
1199
  		list_del(&p->l);
84088ebd1   Lars-Peter Clausen   iio: Add a helper...
1200
1201
  		kfree(p);
  	}
1d892719e   Jonathan Cameron   staging:iio: allo...
1202
  }
1b732888d   Jonathan Cameron   staging:iio: Add ...
1203
1204
1205
1206
  static ssize_t iio_show_dev_name(struct device *dev,
  				 struct device_attribute *attr,
  				 char *buf)
  {
e53f5ac52   Lars-Peter Clausen   iio: Use dev_to_i...
1207
  	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
598db5816   Kees Cook   iio: force snprin...
1208
1209
  	return snprintf(buf, PAGE_SIZE, "%s
  ", indio_dev->name);
1b732888d   Jonathan Cameron   staging:iio: Add ...
1210
1211
1212
  }
  
  static DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL);
bc2b7dab6   Gregor Boirie   iio:core: timesta...
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
  static ssize_t iio_show_timestamp_clock(struct device *dev,
  					struct device_attribute *attr,
  					char *buf)
  {
  	const struct iio_dev *indio_dev = dev_to_iio_dev(dev);
  	const clockid_t clk = iio_device_get_clock(indio_dev);
  	const char *name;
  	ssize_t sz;
  
  	switch (clk) {
  	case CLOCK_REALTIME:
  		name = "realtime
  ";
  		sz = sizeof("realtime
  ");
  		break;
  	case CLOCK_MONOTONIC:
  		name = "monotonic
  ";
  		sz = sizeof("monotonic
  ");
  		break;
  	case CLOCK_MONOTONIC_RAW:
  		name = "monotonic_raw
  ";
  		sz = sizeof("monotonic_raw
  ");
  		break;
  	case CLOCK_REALTIME_COARSE:
  		name = "realtime_coarse
  ";
  		sz = sizeof("realtime_coarse
  ");
  		break;
  	case CLOCK_MONOTONIC_COARSE:
  		name = "monotonic_coarse
  ";
  		sz = sizeof("monotonic_coarse
  ");
  		break;
  	case CLOCK_BOOTTIME:
  		name = "boottime
  ";
  		sz = sizeof("boottime
  ");
  		break;
  	case CLOCK_TAI:
  		name = "tai
  ";
  		sz = sizeof("tai
  ");
  		break;
  	default:
  		BUG();
  	}
  
  	memcpy(buf, name, sz);
  	return sz;
  }
  
  static ssize_t iio_store_timestamp_clock(struct device *dev,
  					 struct device_attribute *attr,
  					 const char *buf, size_t len)
  {
  	clockid_t clk;
  	int ret;
  
  	if (sysfs_streq(buf, "realtime"))
  		clk = CLOCK_REALTIME;
  	else if (sysfs_streq(buf, "monotonic"))
  		clk = CLOCK_MONOTONIC;
  	else if (sysfs_streq(buf, "monotonic_raw"))
  		clk = CLOCK_MONOTONIC_RAW;
  	else if (sysfs_streq(buf, "realtime_coarse"))
  		clk = CLOCK_REALTIME_COARSE;
  	else if (sysfs_streq(buf, "monotonic_coarse"))
  		clk = CLOCK_MONOTONIC_COARSE;
  	else if (sysfs_streq(buf, "boottime"))
  		clk = CLOCK_BOOTTIME;
  	else if (sysfs_streq(buf, "tai"))
  		clk = CLOCK_TAI;
  	else
  		return -EINVAL;
  
  	ret = iio_device_set_clock(dev_to_iio_dev(dev), clk);
  	if (ret)
  		return ret;
  
  	return len;
  }
  
  static DEVICE_ATTR(current_timestamp_clock, S_IRUGO | S_IWUSR,
  		   iio_show_timestamp_clock, iio_store_timestamp_clock);
f8c6f4e9a   Jonathan Cameron   staging:iio:core:...
1306
  static int iio_device_register_sysfs(struct iio_dev *indio_dev)
1d892719e   Jonathan Cameron   staging:iio: allo...
1307
  {
26d25ae3f   Jonathan Cameron   staging:iio: rewo...
1308
  	int i, ret = 0, attrcount, attrn, attrcount_orig = 0;
84088ebd1   Lars-Peter Clausen   iio: Add a helper...
1309
  	struct iio_dev_attr *p;
bc2b7dab6   Gregor Boirie   iio:core: timesta...
1310
  	struct attribute **attr, *clk = NULL;
1d892719e   Jonathan Cameron   staging:iio: allo...
1311

26d25ae3f   Jonathan Cameron   staging:iio: rewo...
1312
  	/* First count elements in any existing group */
f8c6f4e9a   Jonathan Cameron   staging:iio:core:...
1313
1314
  	if (indio_dev->info->attrs) {
  		attr = indio_dev->info->attrs->attrs;
26d25ae3f   Jonathan Cameron   staging:iio: rewo...
1315
1316
  		while (*attr++ != NULL)
  			attrcount_orig++;
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1317
  	}
26d25ae3f   Jonathan Cameron   staging:iio: rewo...
1318
  	attrcount = attrcount_orig;
1d892719e   Jonathan Cameron   staging:iio: allo...
1319
1320
  	/*
  	 * New channel registration method - relies on the fact a group does
d25b3808d   Peter Meerwald   iio: fix typos
1321
  	 * not need to be initialized if its name is NULL.
1d892719e   Jonathan Cameron   staging:iio: allo...
1322
  	 */
f8c6f4e9a   Jonathan Cameron   staging:iio:core:...
1323
1324
  	if (indio_dev->channels)
  		for (i = 0; i < indio_dev->num_channels; i++) {
bc2b7dab6   Gregor Boirie   iio:core: timesta...
1325
1326
1327
1328
1329
1330
1331
  			const struct iio_chan_spec *chan =
  				&indio_dev->channels[i];
  
  			if (chan->type == IIO_TIMESTAMP)
  				clk = &dev_attr_current_timestamp_clock.attr;
  
  			ret = iio_device_add_channel_sysfs(indio_dev, chan);
1d892719e   Jonathan Cameron   staging:iio: allo...
1332
1333
  			if (ret < 0)
  				goto error_clear_attrs;
26d25ae3f   Jonathan Cameron   staging:iio: rewo...
1334
  			attrcount += ret;
1d892719e   Jonathan Cameron   staging:iio: allo...
1335
  		}
26d25ae3f   Jonathan Cameron   staging:iio: rewo...
1336

bc2b7dab6   Gregor Boirie   iio:core: timesta...
1337
1338
  	if (indio_dev->event_interface)
  		clk = &dev_attr_current_timestamp_clock.attr;
f8c6f4e9a   Jonathan Cameron   staging:iio:core:...
1339
  	if (indio_dev->name)
26d25ae3f   Jonathan Cameron   staging:iio: rewo...
1340
  		attrcount++;
bc2b7dab6   Gregor Boirie   iio:core: timesta...
1341
1342
  	if (clk)
  		attrcount++;
26d25ae3f   Jonathan Cameron   staging:iio: rewo...
1343

d83fb1849   Thomas Meyer   staging: iio: Use...
1344
1345
1346
  	indio_dev->chan_attr_group.attrs = kcalloc(attrcount + 1,
  						   sizeof(indio_dev->chan_attr_group.attrs[0]),
  						   GFP_KERNEL);
f8c6f4e9a   Jonathan Cameron   staging:iio:core:...
1347
  	if (indio_dev->chan_attr_group.attrs == NULL) {
26d25ae3f   Jonathan Cameron   staging:iio: rewo...
1348
1349
  		ret = -ENOMEM;
  		goto error_clear_attrs;
1b732888d   Jonathan Cameron   staging:iio: Add ...
1350
  	}
26d25ae3f   Jonathan Cameron   staging:iio: rewo...
1351
  	/* Copy across original attributes */
f8c6f4e9a   Jonathan Cameron   staging:iio:core:...
1352
1353
1354
1355
  	if (indio_dev->info->attrs)
  		memcpy(indio_dev->chan_attr_group.attrs,
  		       indio_dev->info->attrs->attrs,
  		       sizeof(indio_dev->chan_attr_group.attrs[0])
26d25ae3f   Jonathan Cameron   staging:iio: rewo...
1356
1357
1358
  		       *attrcount_orig);
  	attrn = attrcount_orig;
  	/* Add all elements from the list. */
f8c6f4e9a   Jonathan Cameron   staging:iio:core:...
1359
1360
1361
1362
  	list_for_each_entry(p, &indio_dev->channel_attr_list, l)
  		indio_dev->chan_attr_group.attrs[attrn++] = &p->dev_attr.attr;
  	if (indio_dev->name)
  		indio_dev->chan_attr_group.attrs[attrn++] = &dev_attr_name.attr;
bc2b7dab6   Gregor Boirie   iio:core: timesta...
1363
1364
  	if (clk)
  		indio_dev->chan_attr_group.attrs[attrn++] = clk;
26d25ae3f   Jonathan Cameron   staging:iio: rewo...
1365

f8c6f4e9a   Jonathan Cameron   staging:iio:core:...
1366
1367
  	indio_dev->groups[indio_dev->groupcounter++] =
  		&indio_dev->chan_attr_group;
26d25ae3f   Jonathan Cameron   staging:iio: rewo...
1368

1d892719e   Jonathan Cameron   staging:iio: allo...
1369
  	return 0;
1b732888d   Jonathan Cameron   staging:iio: Add ...
1370

1d892719e   Jonathan Cameron   staging:iio: allo...
1371
  error_clear_attrs:
84088ebd1   Lars-Peter Clausen   iio: Add a helper...
1372
  	iio_free_chan_devattr_list(&indio_dev->channel_attr_list);
1d892719e   Jonathan Cameron   staging:iio: allo...
1373

26d25ae3f   Jonathan Cameron   staging:iio: rewo...
1374
  	return ret;
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1375
  }
f8c6f4e9a   Jonathan Cameron   staging:iio:core:...
1376
  static void iio_device_unregister_sysfs(struct iio_dev *indio_dev)
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1377
  {
1d892719e   Jonathan Cameron   staging:iio: allo...
1378

84088ebd1   Lars-Peter Clausen   iio: Add a helper...
1379
  	iio_free_chan_devattr_list(&indio_dev->channel_attr_list);
f8c6f4e9a   Jonathan Cameron   staging:iio:core:...
1380
  	kfree(indio_dev->chan_attr_group.attrs);
c1b03ab5e   Martin Fuzzey   iio: core: Fix do...
1381
  	indio_dev->chan_attr_group.attrs = NULL;
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1382
  }
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1383
1384
  static void iio_dev_release(struct device *device)
  {
e53f5ac52   Lars-Peter Clausen   iio: Use dev_to_i...
1385
  	struct iio_dev *indio_dev = dev_to_iio_dev(device);
d89e119a0   Benjamin Gaignard   iio: add hardware...
1386
  	if (indio_dev->modes & INDIO_ALL_TRIGGERED_MODES)
f8c6f4e9a   Jonathan Cameron   staging:iio:core:...
1387
1388
1389
  		iio_device_unregister_trigger_consumer(indio_dev);
  	iio_device_unregister_eventset(indio_dev);
  	iio_device_unregister_sysfs(indio_dev);
e407fd655   Lars-Peter Clausen   iio: Fix potentia...
1390

9e69c935f   Lars-Peter Clausen   iio: Add referenc...
1391
  	iio_buffer_put(indio_dev->buffer);
e407fd655   Lars-Peter Clausen   iio: Fix potentia...
1392
1393
  	ida_simple_remove(&iio_ida, indio_dev->id);
  	kfree(indio_dev);
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1394
  }
17d82b47a   Guenter Roeck   iio: Add OF support
1395
  struct device_type iio_device_type = {
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1396
1397
1398
  	.name = "iio_device",
  	.release = iio_dev_release,
  };
a7e57dce0   Sachin Kamat   iio: core: Move k...
1399
1400
1401
1402
  /**
   * iio_device_alloc() - allocate an iio_dev from a driver
   * @sizeof_priv:	Space to allocate for private structure.
   **/
7cbb75370   Lars-Peter Clausen   staging:iio: Stre...
1403
  struct iio_dev *iio_device_alloc(int sizeof_priv)
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1404
  {
6f7c8ee58   Jonathan Cameron   staging:iio: Add ...
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
  	struct iio_dev *dev;
  	size_t alloc_size;
  
  	alloc_size = sizeof(struct iio_dev);
  	if (sizeof_priv) {
  		alloc_size = ALIGN(alloc_size, IIO_ALIGN);
  		alloc_size += sizeof_priv;
  	}
  	/* ensure 32-byte alignment of whole construct ? */
  	alloc_size += IIO_ALIGN - 1;
  
  	dev = kzalloc(alloc_size, GFP_KERNEL);
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1417
1418
  
  	if (dev) {
26d25ae3f   Jonathan Cameron   staging:iio: rewo...
1419
  		dev->dev.groups = dev->groups;
17d82b47a   Guenter Roeck   iio: Add OF support
1420
  		dev->dev.type = &iio_device_type;
5aaaeba82   Jonathan Cameron   staging: iio: Mov...
1421
  		dev->dev.bus = &iio_bus_type;
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1422
1423
1424
  		device_initialize(&dev->dev);
  		dev_set_drvdata(&dev->dev, (void *)dev);
  		mutex_init(&dev->mlock);
ac917a811   Jonathan Cameron   staging:iio:core ...
1425
  		mutex_init(&dev->info_exist_lock);
e407fd655   Lars-Peter Clausen   iio: Fix potentia...
1426
  		INIT_LIST_HEAD(&dev->channel_attr_list);
a9e39f9e8   Jonathan Cameron   staging:iio: move...
1427
1428
1429
1430
  
  		dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL);
  		if (dev->id < 0) {
  			/* cannot use a dev_err as the name isn't available */
3176dd5d3   Sachin Kamat   iio: core: Use pr...
1431
1432
  			pr_err("failed to get device id
  ");
a9e39f9e8   Jonathan Cameron   staging:iio: move...
1433
1434
1435
1436
  			kfree(dev);
  			return NULL;
  		}
  		dev_set_name(&dev->dev, "iio:device%d", dev->id);
84b36ce5f   Jonathan Cameron   staging:iio: Add ...
1437
  		INIT_LIST_HEAD(&dev->buffer_list);
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1438
1439
1440
1441
  	}
  
  	return dev;
  }
7cbb75370   Lars-Peter Clausen   staging:iio: Stre...
1442
  EXPORT_SYMBOL(iio_device_alloc);
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1443

a7e57dce0   Sachin Kamat   iio: core: Move k...
1444
1445
1446
1447
  /**
   * iio_device_free() - free an iio_dev from a driver
   * @dev:		the iio_dev associated with the device
   **/
7cbb75370   Lars-Peter Clausen   staging:iio: Stre...
1448
  void iio_device_free(struct iio_dev *dev)
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1449
  {
e407fd655   Lars-Peter Clausen   iio: Fix potentia...
1450
1451
  	if (dev)
  		put_device(&dev->dev);
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1452
  }
7cbb75370   Lars-Peter Clausen   staging:iio: Stre...
1453
  EXPORT_SYMBOL(iio_device_free);
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1454

9dabaf5ed   Grygorii Strashko   iio: core: implem...
1455
1456
1457
1458
  static void devm_iio_device_release(struct device *dev, void *res)
  {
  	iio_device_free(*(struct iio_dev **)res);
  }
70e483487   Gregor Boirie   iio: add resource...
1459
  int devm_iio_device_match(struct device *dev, void *res, void *data)
9dabaf5ed   Grygorii Strashko   iio: core: implem...
1460
1461
1462
1463
1464
1465
1466
1467
  {
  	struct iio_dev **r = res;
  	if (!r || !*r) {
  		WARN_ON(!r || !*r);
  		return 0;
  	}
  	return *r == data;
  }
70e483487   Gregor Boirie   iio: add resource...
1468
  EXPORT_SYMBOL_GPL(devm_iio_device_match);
9dabaf5ed   Grygorii Strashko   iio: core: implem...
1469

a7e57dce0   Sachin Kamat   iio: core: Move k...
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
  /**
   * devm_iio_device_alloc - Resource-managed iio_device_alloc()
   * @dev:		Device to allocate iio_dev for
   * @sizeof_priv:	Space to allocate for private structure.
   *
   * Managed iio_device_alloc. iio_dev allocated with this function is
   * automatically freed on driver detach.
   *
   * If an iio_dev allocated with this function needs to be freed separately,
   * devm_iio_device_free() must be used.
   *
   * RETURNS:
   * Pointer to allocated iio_dev on success, NULL on failure.
   */
9dabaf5ed   Grygorii Strashko   iio: core: implem...
1484
1485
1486
1487
1488
1489
1490
1491
  struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv)
  {
  	struct iio_dev **ptr, *iio_dev;
  
  	ptr = devres_alloc(devm_iio_device_release, sizeof(*ptr),
  			   GFP_KERNEL);
  	if (!ptr)
  		return NULL;
9dabaf5ed   Grygorii Strashko   iio: core: implem...
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
  	iio_dev = iio_device_alloc(sizeof_priv);
  	if (iio_dev) {
  		*ptr = iio_dev;
  		devres_add(dev, ptr);
  	} else {
  		devres_free(ptr);
  	}
  
  	return iio_dev;
  }
  EXPORT_SYMBOL_GPL(devm_iio_device_alloc);
a7e57dce0   Sachin Kamat   iio: core: Move k...
1503
1504
1505
1506
1507
1508
1509
  /**
   * devm_iio_device_free - Resource-managed iio_device_free()
   * @dev:		Device this iio_dev belongs to
   * @iio_dev:		the iio_dev associated with the device
   *
   * Free iio_dev allocated with devm_iio_device_alloc().
   */
9dabaf5ed   Grygorii Strashko   iio: core: implem...
1510
1511
1512
1513
1514
1515
1516
1517
1518
  void devm_iio_device_free(struct device *dev, struct iio_dev *iio_dev)
  {
  	int rc;
  
  	rc = devres_release(dev, devm_iio_device_release,
  			    devm_iio_device_match, iio_dev);
  	WARN_ON(rc);
  }
  EXPORT_SYMBOL_GPL(devm_iio_device_free);
1aa042783   Jonathan Cameron   staging: iio: pus...
1519
  /**
14555b144   Jonathan Cameron   staging:iio: repl...
1520
   * iio_chrdev_open() - chrdev file open for buffer access and ioctls
2498dcf6e   Cristina Opriceana   iio: core: Add fu...
1521
1522
1523
1524
1525
   * @inode:	Inode structure for identifying the device in the file system
   * @filp:	File structure for iio device used to keep and later access
   *		private data
   *
   * Return: 0 on success or -EBUSY if the device is already opened
1aa042783   Jonathan Cameron   staging: iio: pus...
1526
1527
1528
   **/
  static int iio_chrdev_open(struct inode *inode, struct file *filp)
  {
f8c6f4e9a   Jonathan Cameron   staging:iio:core:...
1529
  	struct iio_dev *indio_dev = container_of(inode->i_cdev,
1aa042783   Jonathan Cameron   staging: iio: pus...
1530
  						struct iio_dev, chrdev);
bb01443e2   Lars-Peter Clausen   staging:iio: Make...
1531
1532
1533
  
  	if (test_and_set_bit(IIO_BUSY_BIT_POS, &indio_dev->flags))
  		return -EBUSY;
cadc2125e   Lars-Peter Clausen   iio: fix: Keep a ...
1534
  	iio_device_get(indio_dev);
f8c6f4e9a   Jonathan Cameron   staging:iio:core:...
1535
  	filp->private_data = indio_dev;
30eb82f05   Jonathan Cameron   staging:iio: Prev...
1536

793351404   Lars-Peter Clausen   staging:iio: Drop...
1537
  	return 0;
1aa042783   Jonathan Cameron   staging: iio: pus...
1538
1539
1540
  }
  
  /**
14555b144   Jonathan Cameron   staging:iio: repl...
1541
   * iio_chrdev_release() - chrdev file close buffer access and ioctls
2498dcf6e   Cristina Opriceana   iio: core: Add fu...
1542
1543
1544
1545
1546
   * @inode:	Inode structure pointer for the char device
   * @filp:	File structure pointer for the char device
   *
   * Return: 0 for successful release
   */
1aa042783   Jonathan Cameron   staging: iio: pus...
1547
1548
  static int iio_chrdev_release(struct inode *inode, struct file *filp)
  {
bb01443e2   Lars-Peter Clausen   staging:iio: Make...
1549
1550
  	struct iio_dev *indio_dev = container_of(inode->i_cdev,
  						struct iio_dev, chrdev);
bb01443e2   Lars-Peter Clausen   staging:iio: Make...
1551
  	clear_bit(IIO_BUSY_BIT_POS, &indio_dev->flags);
cadc2125e   Lars-Peter Clausen   iio: fix: Keep a ...
1552
  	iio_device_put(indio_dev);
1aa042783   Jonathan Cameron   staging: iio: pus...
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
  	return 0;
  }
  
  /* Somewhat of a cross file organization violation - ioctls here are actually
   * event related */
  static long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  {
  	struct iio_dev *indio_dev = filp->private_data;
  	int __user *ip = (int __user *)arg;
  	int fd;
f18e7a068   Lars-Peter Clausen   iio: Return -ENOD...
1563
1564
  	if (!indio_dev->info)
  		return -ENODEV;
1aa042783   Jonathan Cameron   staging: iio: pus...
1565
1566
  	if (cmd == IIO_GET_EVENT_FD_IOCTL) {
  		fd = iio_event_getfd(indio_dev);
3f9059b71   Linus Walleij   iio: percolate er...
1567
1568
  		if (fd < 0)
  			return fd;
1aa042783   Jonathan Cameron   staging: iio: pus...
1569
1570
1571
1572
1573
1574
  		if (copy_to_user(ip, &fd, sizeof(fd)))
  			return -EFAULT;
  		return 0;
  	}
  	return -EINVAL;
  }
14555b144   Jonathan Cameron   staging:iio: repl...
1575
1576
  static const struct file_operations iio_buffer_fileops = {
  	.read = iio_buffer_read_first_n_outer_addr,
1aa042783   Jonathan Cameron   staging: iio: pus...
1577
1578
  	.release = iio_chrdev_release,
  	.open = iio_chrdev_open,
14555b144   Jonathan Cameron   staging:iio: repl...
1579
  	.poll = iio_buffer_poll_addr,
1aa042783   Jonathan Cameron   staging: iio: pus...
1580
1581
1582
1583
1584
  	.owner = THIS_MODULE,
  	.llseek = noop_llseek,
  	.unlocked_ioctl = iio_ioctl,
  	.compat_ioctl = iio_ioctl,
  };
8f5d8727a   Vlad Dogaru   iio: ensure scan ...
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
  static int iio_check_unique_scan_index(struct iio_dev *indio_dev)
  {
  	int i, j;
  	const struct iio_chan_spec *channels = indio_dev->channels;
  
  	if (!(indio_dev->modes & INDIO_ALL_BUFFER_MODES))
  		return 0;
  
  	for (i = 0; i < indio_dev->num_channels - 1; i++) {
  		if (channels[i].scan_index < 0)
  			continue;
  		for (j = i + 1; j < indio_dev->num_channels; j++)
  			if (channels[i].scan_index == channels[j].scan_index) {
  				dev_err(&indio_dev->dev,
  					"Duplicate scan index %d
  ",
  					channels[i].scan_index);
  				return -EINVAL;
  			}
  	}
  
  	return 0;
  }
0f1acee5f   Michael Hennerich   staging: iio: cor...
1608
  static const struct iio_buffer_setup_ops noop_ring_setup_ops;
63b19547c   Jonathan Cameron   iio: Use macro ma...
1609
  int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod)
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1610
1611
  {
  	int ret;
63b19547c   Jonathan Cameron   iio: Use macro ma...
1612
  	indio_dev->driver_module = this_mod;
17d82b47a   Guenter Roeck   iio: Add OF support
1613
1614
1615
  	/* If the calling driver did not initialize of_node, do it here */
  	if (!indio_dev->dev.of_node && indio_dev->dev.parent)
  		indio_dev->dev.of_node = indio_dev->dev.parent->of_node;
8f5d8727a   Vlad Dogaru   iio: ensure scan ...
1616
1617
1618
  	ret = iio_check_unique_scan_index(indio_dev);
  	if (ret < 0)
  		return ret;
d45ebf1f9   Andi Shyti   iio: core: check ...
1619
1620
  	if (!indio_dev->info)
  		return -EINVAL;
1aa042783   Jonathan Cameron   staging: iio: pus...
1621
  	/* configure elements for the chrdev */
f8c6f4e9a   Jonathan Cameron   staging:iio:core:...
1622
  	indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id);
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1623

8915aacac   Greg Kroah-Hartman   iio: core: no nee...
1624
  	iio_device_register_debugfs(indio_dev);
3e1b6c95b   Lars-Peter Clausen   iio: Move buffer ...
1625
1626
1627
1628
1629
1630
1631
1632
  
  	ret = iio_buffer_alloc_sysfs_and_mask(indio_dev);
  	if (ret) {
  		dev_err(indio_dev->dev.parent,
  			"Failed to create buffer sysfs interfaces
  ");
  		goto error_unreg_debugfs;
  	}
f8c6f4e9a   Jonathan Cameron   staging:iio:core:...
1633
  	ret = iio_device_register_sysfs(indio_dev);
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1634
  	if (ret) {
f8c6f4e9a   Jonathan Cameron   staging:iio:core:...
1635
  		dev_err(indio_dev->dev.parent,
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1636
1637
  			"Failed to register sysfs interfaces
  ");
3e1b6c95b   Lars-Peter Clausen   iio: Move buffer ...
1638
  		goto error_buffer_free_sysfs;
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1639
  	}
f8c6f4e9a   Jonathan Cameron   staging:iio:core:...
1640
  	ret = iio_device_register_eventset(indio_dev);
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1641
  	if (ret) {
f8c6f4e9a   Jonathan Cameron   staging:iio:core:...
1642
  		dev_err(indio_dev->dev.parent,
c849d2538   Roel Van Nyen   Staging: iio: Fix...
1643
1644
  			"Failed to register event set
  ");
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1645
1646
  		goto error_free_sysfs;
  	}
d89e119a0   Benjamin Gaignard   iio: add hardware...
1647
  	if (indio_dev->modes & INDIO_ALL_TRIGGERED_MODES)
f8c6f4e9a   Jonathan Cameron   staging:iio:core:...
1648
  		iio_device_register_trigger_consumer(indio_dev);
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1649

0f1acee5f   Michael Hennerich   staging: iio: cor...
1650
1651
1652
  	if ((indio_dev->modes & INDIO_ALL_BUFFER_MODES) &&
  		indio_dev->setup_ops == NULL)
  		indio_dev->setup_ops = &noop_ring_setup_ops;
f8c6f4e9a   Jonathan Cameron   staging:iio:core:...
1653
  	cdev_init(&indio_dev->chrdev, &iio_buffer_fileops);
63b19547c   Jonathan Cameron   iio: Use macro ma...
1654
1655
  
  	indio_dev->chrdev.owner = this_mod;
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1656

38923911d   Logan Gunthorpe   iio:core: utilize...
1657
  	ret = cdev_device_add(&indio_dev->chrdev, &indio_dev->dev);
0d5b7dae8   Lars-Peter Clausen   iio: Prevent race...
1658
  	if (ret < 0)
38923911d   Logan Gunthorpe   iio:core: utilize...
1659
  		goto error_unreg_eventset;
0d5b7dae8   Lars-Peter Clausen   iio: Prevent race...
1660
1661
  
  	return 0;
38923911d   Logan Gunthorpe   iio:core: utilize...
1662

26d25ae3f   Jonathan Cameron   staging:iio: rewo...
1663
  error_unreg_eventset:
f8c6f4e9a   Jonathan Cameron   staging:iio:core:...
1664
  	iio_device_unregister_eventset(indio_dev);
26d25ae3f   Jonathan Cameron   staging:iio: rewo...
1665
  error_free_sysfs:
f8c6f4e9a   Jonathan Cameron   staging:iio:core:...
1666
  	iio_device_unregister_sysfs(indio_dev);
3e1b6c95b   Lars-Peter Clausen   iio: Move buffer ...
1667
1668
  error_buffer_free_sysfs:
  	iio_buffer_free_sysfs_and_mask(indio_dev);
e553f182d   Michael Hennerich   staging: iio: cor...
1669
1670
  error_unreg_debugfs:
  	iio_device_unregister_debugfs(indio_dev);
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1671
1672
  	return ret;
  }
63b19547c   Jonathan Cameron   iio: Use macro ma...
1673
  EXPORT_SYMBOL(__iio_device_register);
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1674

a7e57dce0   Sachin Kamat   iio: core: Move k...
1675
1676
1677
1678
  /**
   * iio_device_unregister() - unregister a device from the IIO subsystem
   * @indio_dev:		Device structure representing the device.
   **/
f8c6f4e9a   Jonathan Cameron   staging:iio:core:...
1679
  void iio_device_unregister(struct iio_dev *indio_dev)
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1680
  {
38923911d   Logan Gunthorpe   iio:core: utilize...
1681
  	cdev_device_del(&indio_dev->chrdev, &indio_dev->dev);
a87c82e45   Lars-Peter Clausen   iio: Stop samplin...
1682

7f75591fc   Fabrice Gasnier   iio: core: fix a ...
1683
  	mutex_lock(&indio_dev->info_exist_lock);
bc4c96129   Lars-Peter Clausen   iio: Remove debug...
1684
  	iio_device_unregister_debugfs(indio_dev);
0d5b7dae8   Lars-Peter Clausen   iio: Prevent race...
1685

a87c82e45   Lars-Peter Clausen   iio: Stop samplin...
1686
  	iio_disable_all_buffers(indio_dev);
ac917a811   Jonathan Cameron   staging:iio:core ...
1687
  	indio_dev->info = NULL;
d2f0a48f3   Lars-Peter Clausen   iio: Wakeup poll ...
1688
1689
1690
  
  	iio_device_wakeup_eventset(indio_dev);
  	iio_buffer_wakeup_poll(indio_dev);
ac917a811   Jonathan Cameron   staging:iio:core ...
1691
  	mutex_unlock(&indio_dev->info_exist_lock);
3e1b6c95b   Lars-Peter Clausen   iio: Move buffer ...
1692
1693
  
  	iio_buffer_free_sysfs_and_mask(indio_dev);
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1694
1695
  }
  EXPORT_SYMBOL(iio_device_unregister);
8caa07c0e   Sachin Kamat   iio: core: Implem...
1696
1697
1698
1699
1700
  
  static void devm_iio_device_unreg(struct device *dev, void *res)
  {
  	iio_device_unregister(*(struct iio_dev **)res);
  }
63b19547c   Jonathan Cameron   iio: Use macro ma...
1701
1702
  int __devm_iio_device_register(struct device *dev, struct iio_dev *indio_dev,
  			       struct module *this_mod)
8caa07c0e   Sachin Kamat   iio: core: Implem...
1703
1704
1705
1706
1707
1708
1709
1710
1711
  {
  	struct iio_dev **ptr;
  	int ret;
  
  	ptr = devres_alloc(devm_iio_device_unreg, sizeof(*ptr), GFP_KERNEL);
  	if (!ptr)
  		return -ENOMEM;
  
  	*ptr = indio_dev;
63b19547c   Jonathan Cameron   iio: Use macro ma...
1712
  	ret = __iio_device_register(indio_dev, this_mod);
8caa07c0e   Sachin Kamat   iio: core: Implem...
1713
1714
1715
1716
1717
1718
1719
  	if (!ret)
  		devres_add(dev, ptr);
  	else
  		devres_free(ptr);
  
  	return ret;
  }
63b19547c   Jonathan Cameron   iio: Use macro ma...
1720
  EXPORT_SYMBOL_GPL(__devm_iio_device_register);
8caa07c0e   Sachin Kamat   iio: core: Implem...
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
  
  /**
   * devm_iio_device_unregister - Resource-managed iio_device_unregister()
   * @dev:	Device this iio_dev belongs to
   * @indio_dev:	the iio_dev associated with the device
   *
   * Unregister iio_dev registered with devm_iio_device_register().
   */
  void devm_iio_device_unregister(struct device *dev, struct iio_dev *indio_dev)
  {
  	int rc;
  
  	rc = devres_release(dev, devm_iio_device_unreg,
  			    devm_iio_device_match, indio_dev);
  	WARN_ON(rc);
  }
  EXPORT_SYMBOL_GPL(devm_iio_device_unregister);
08a338055   Alison Schofield   iio: core: implem...
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
  /**
   * iio_device_claim_direct_mode - Keep device in direct mode
   * @indio_dev:	the iio_dev associated with the device
   *
   * If the device is in direct mode it is guaranteed to stay
   * that way until iio_device_release_direct_mode() is called.
   *
   * Use with iio_device_release_direct_mode()
   *
   * Returns: 0 on success, -EBUSY on failure
   */
  int iio_device_claim_direct_mode(struct iio_dev *indio_dev)
  {
  	mutex_lock(&indio_dev->mlock);
  
  	if (iio_buffer_enabled(indio_dev)) {
  		mutex_unlock(&indio_dev->mlock);
  		return -EBUSY;
  	}
  	return 0;
  }
  EXPORT_SYMBOL_GPL(iio_device_claim_direct_mode);
  
  /**
   * iio_device_release_direct_mode - releases claim on direct mode
   * @indio_dev:	the iio_dev associated with the device
   *
   * Release the claim. Device is no longer guaranteed to stay
   * in direct mode.
   *
   * Use with iio_device_claim_direct_mode()
   */
  void iio_device_release_direct_mode(struct iio_dev *indio_dev)
  {
  	mutex_unlock(&indio_dev->mlock);
  }
  EXPORT_SYMBOL_GPL(iio_device_release_direct_mode);
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1775
1776
  subsys_initcall(iio_init);
  module_exit(iio_exit);
c8b95952e   Jonathan Cameron   IIO: Update email...
1777
  MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
847ec80bb   Jonathan Cameron   Staging: IIO: cor...
1778
1779
  MODULE_DESCRIPTION("Industrial I/O core");
  MODULE_LICENSE("GPL");