aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/iio
diff options
context:
space:
mode:
authorMichael Hennerich <michael.hennerich@analog.com>2012-03-01 04:51:03 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-03-02 19:35:39 -0500
commite553f182d55bd268fea3f106368e2344141c212a (patch)
tree0203a2d354d4f61001f4f2a89bdc39d3094c75a2 /drivers/staging/iio
parent4abf6f8b29e37f492078173a9d4cb808ce327ec0 (diff)
staging: iio: core: Introduce debugfs support, add support for direct register access
Changes since V1: Exclude iio debugfs code in case CONFIG_DEBUG_FS isn't enabled. Introduce helper function iio_get_debugfs_dentry. Document additions to struct iio_dev iio_debugfs_read_reg: Use snprintf. Use a shorter fixed length. Introduce len instead of pointer math. iio_debugfs_write_reg: Fix return value use PT_ERR. Changes since V2: Use debugfs_remove. Fix whitespace damage. Signed-off-by: Michael Hennerich <michael.hennerich@analog.com> Acked-by: Jonathan Cameron <jic23@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/iio')
-rw-r--r--drivers/staging/iio/iio.h27
-rw-r--r--drivers/staging/iio/industrialio-core.c137
2 files changed, 162 insertions, 2 deletions
diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h
index 6aa31e52c26..b9cd454f69e 100644
--- a/drivers/staging/iio/iio.h
+++ b/drivers/staging/iio/iio.h
@@ -286,6 +286,9 @@ struct iio_info {
286 struct iio_trigger *trig); 286 struct iio_trigger *trig);
287 int (*update_scan_mode)(struct iio_dev *indio_dev, 287 int (*update_scan_mode)(struct iio_dev *indio_dev,
288 const unsigned long *scan_mask); 288 const unsigned long *scan_mask);
289 int (*debugfs_reg_access)(struct iio_dev *indio_dev,
290 unsigned reg, unsigned writeval,
291 unsigned *readval);
289}; 292};
290 293
291/** 294/**
@@ -332,7 +335,9 @@ struct iio_buffer_setup_ops {
332 * @groups: [INTERN] attribute groups 335 * @groups: [INTERN] attribute groups
333 * @groupcounter: [INTERN] index of next attribute group 336 * @groupcounter: [INTERN] index of next attribute group
334 * @flags: [INTERN] file ops related flags including busy flag. 337 * @flags: [INTERN] file ops related flags including busy flag.
335 **/ 338 * @debugfs_dentry: [INTERN] device specific debugfs dentry.
339 * @cached_reg_addr: [INTERN] cached register address for debugfs reads.
340 */
336struct iio_dev { 341struct iio_dev {
337 int id; 342 int id;
338 343
@@ -366,6 +371,10 @@ struct iio_dev {
366 int groupcounter; 371 int groupcounter;
367 372
368 unsigned long flags; 373 unsigned long flags;
374#if defined(CONFIG_DEBUG_FS)
375 struct dentry *debugfs_dentry;
376 unsigned cached_reg_addr;
377#endif
369}; 378};
370 379
371/** 380/**
@@ -443,4 +452,20 @@ static inline bool iio_buffer_enabled(struct iio_dev *indio_dev)
443 & (INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE); 452 & (INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE);
444}; 453};
445 454
455/**
456 * iio_get_debugfs_dentry() - helper function to get the debugfs_dentry
457 * @indio_dev: IIO device info structure for device
458 **/
459#if defined(CONFIG_DEBUG_FS)
460static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev)
461{
462 return indio_dev->debugfs_dentry;
463};
464#else
465static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev)
466{
467 return NULL;
468};
469#endif
470
446#endif /* _INDUSTRIAL_IO_H_ */ 471#endif /* _INDUSTRIAL_IO_H_ */
diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c
index 0b8ba8f1483..868e3667200 100644
--- a/drivers/staging/iio/industrialio-core.c
+++ b/drivers/staging/iio/industrialio-core.c
@@ -22,6 +22,7 @@
22#include <linux/cdev.h> 22#include <linux/cdev.h>
23#include <linux/slab.h> 23#include <linux/slab.h>
24#include <linux/anon_inodes.h> 24#include <linux/anon_inodes.h>
25#include <linux/debugfs.h>
25#include "iio.h" 26#include "iio.h"
26#include "iio_core.h" 27#include "iio_core.h"
27#include "iio_core_trigger.h" 28#include "iio_core_trigger.h"
@@ -39,6 +40,8 @@ struct bus_type iio_bus_type = {
39}; 40};
40EXPORT_SYMBOL(iio_bus_type); 41EXPORT_SYMBOL(iio_bus_type);
41 42
43static struct dentry *iio_debugfs_dentry;
44
42static const char * const iio_data_type_name[] = { 45static const char * const iio_data_type_name[] = {
43 [IIO_RAW] = "raw", 46 [IIO_RAW] = "raw",
44 [IIO_PROCESSED] = "input", 47 [IIO_PROCESSED] = "input",
@@ -129,6 +132,8 @@ static int __init iio_init(void)
129 goto error_unregister_bus_type; 132 goto error_unregister_bus_type;
130 } 133 }
131 134
135 iio_debugfs_dentry = debugfs_create_dir("iio", NULL);
136
132 return 0; 137 return 0;
133 138
134error_unregister_bus_type: 139error_unregister_bus_type:
@@ -142,6 +147,84 @@ static void __exit iio_exit(void)
142 if (iio_devt) 147 if (iio_devt)
143 unregister_chrdev_region(iio_devt, IIO_DEV_MAX); 148 unregister_chrdev_region(iio_devt, IIO_DEV_MAX);
144 bus_unregister(&iio_bus_type); 149 bus_unregister(&iio_bus_type);
150 debugfs_remove(iio_debugfs_dentry);
151}
152
153#if defined(CONFIG_DEBUG_FS)
154static int iio_debugfs_open(struct inode *inode, struct file *file)
155{
156 if (inode->i_private)
157 file->private_data = inode->i_private;
158
159 return 0;
160}
161
162static ssize_t iio_debugfs_read_reg(struct file *file, char __user *userbuf,
163 size_t count, loff_t *ppos)
164{
165 struct iio_dev *indio_dev = file->private_data;
166 char buf[20];
167 unsigned val = 0;
168 ssize_t len;
169 int ret;
170
171 ret = indio_dev->info->debugfs_reg_access(indio_dev,
172 indio_dev->cached_reg_addr,
173 0, &val);
174 if (ret)
175 dev_err(indio_dev->dev.parent, "%s: read failed\n", __func__);
176
177 len = snprintf(buf, sizeof(buf), "0x%X\n", val);
178
179 return simple_read_from_buffer(userbuf, count, ppos, buf, len);
180}
181
182static ssize_t iio_debugfs_write_reg(struct file *file,
183 const char __user *userbuf, size_t count, loff_t *ppos)
184{
185 struct iio_dev *indio_dev = file->private_data;
186 unsigned reg, val;
187 char buf[80];
188 int ret;
189
190 count = min_t(size_t, count, (sizeof(buf)-1));
191 if (copy_from_user(buf, userbuf, count))
192 return -EFAULT;
193
194 buf[count] = 0;
195
196 ret = sscanf(buf, "%i %i", &reg, &val);
197
198 switch (ret) {
199 case 1:
200 indio_dev->cached_reg_addr = reg;
201 break;
202 case 2:
203 indio_dev->cached_reg_addr = reg;
204 ret = indio_dev->info->debugfs_reg_access(indio_dev, reg,
205 val, NULL);
206 if (ret) {
207 dev_err(indio_dev->dev.parent, "%s: write failed\n",
208 __func__);
209 return ret;
210 }
211 break;
212 default:
213 return -EINVAL;
214 }
215
216 return count;
217}
218
219static const struct file_operations iio_debugfs_reg_fops = {
220 .open = iio_debugfs_open,
221 .read = iio_debugfs_read_reg,
222 .write = iio_debugfs_write_reg,
223};
224
225static void iio_device_unregister_debugfs(struct iio_dev *indio_dev)
226{
227 debugfs_remove_recursive(indio_dev->debugfs_dentry);
145} 228}
146 229
147static ssize_t iio_read_channel_ext_info(struct device *dev, 230static ssize_t iio_read_channel_ext_info(struct device *dev,
@@ -171,6 +254,49 @@ static ssize_t iio_write_channel_ext_info(struct device *dev,
171 return ext_info->write(indio_dev, this_attr->c, buf, len); 254 return ext_info->write(indio_dev, this_attr->c, buf, len);
172} 255}
173 256
257static int iio_device_register_debugfs(struct iio_dev *indio_dev)
258{
259 struct dentry *d;
260
261 if (indio_dev->info->debugfs_reg_access == NULL)
262 return 0;
263
264 if (IS_ERR(iio_debugfs_dentry))
265 return 0;
266
267 indio_dev->debugfs_dentry =
268 debugfs_create_dir(dev_name(&indio_dev->dev),
269 iio_debugfs_dentry);
270 if (IS_ERR(indio_dev->debugfs_dentry))
271 return PTR_ERR(indio_dev->debugfs_dentry);
272
273 if (indio_dev->debugfs_dentry == NULL) {
274 dev_warn(indio_dev->dev.parent,
275 "Failed to create debugfs directory\n");
276 return -EFAULT;
277 }
278
279 d = debugfs_create_file("direct_reg_access", 0644,
280 indio_dev->debugfs_dentry,
281 indio_dev, &iio_debugfs_reg_fops);
282 if (!d) {
283 iio_device_unregister_debugfs(indio_dev);
284 return -ENOMEM;
285 }
286
287 return 0;
288}
289#else
290static int iio_device_register_debugfs(struct iio_dev *indio_dev)
291{
292 return 0;
293}
294
295static void iio_device_unregister_debugfs(struct iio_dev *indio_dev)
296{
297}
298#endif /* CONFIG_DEBUG_FS */
299
174static ssize_t iio_read_channel_info(struct device *dev, 300static ssize_t iio_read_channel_info(struct device *dev,
175 struct device_attribute *attr, 301 struct device_attribute *attr,
176 char *buf) 302 char *buf)
@@ -618,6 +744,7 @@ static void iio_dev_release(struct device *device)
618 iio_device_unregister_trigger_consumer(indio_dev); 744 iio_device_unregister_trigger_consumer(indio_dev);
619 iio_device_unregister_eventset(indio_dev); 745 iio_device_unregister_eventset(indio_dev);
620 iio_device_unregister_sysfs(indio_dev); 746 iio_device_unregister_sysfs(indio_dev);
747 iio_device_unregister_debugfs(indio_dev);
621} 748}
622 749
623static struct device_type iio_dev_type = { 750static struct device_type iio_dev_type = {
@@ -734,11 +861,17 @@ int iio_device_register(struct iio_dev *indio_dev)
734 /* configure elements for the chrdev */ 861 /* configure elements for the chrdev */
735 indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id); 862 indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id);
736 863
864 ret = iio_device_register_debugfs(indio_dev);
865 if (ret) {
866 dev_err(indio_dev->dev.parent,
867 "Failed to register debugfs interfaces\n");
868 goto error_ret;
869 }
737 ret = iio_device_register_sysfs(indio_dev); 870 ret = iio_device_register_sysfs(indio_dev);
738 if (ret) { 871 if (ret) {
739 dev_err(indio_dev->dev.parent, 872 dev_err(indio_dev->dev.parent,
740 "Failed to register sysfs interfaces\n"); 873 "Failed to register sysfs interfaces\n");
741 goto error_ret; 874 goto error_unreg_debugfs;
742 } 875 }
743 ret = iio_device_register_eventset(indio_dev); 876 ret = iio_device_register_eventset(indio_dev);
744 if (ret) { 877 if (ret) {
@@ -765,6 +898,8 @@ error_unreg_eventset:
765 iio_device_unregister_eventset(indio_dev); 898 iio_device_unregister_eventset(indio_dev);
766error_free_sysfs: 899error_free_sysfs:
767 iio_device_unregister_sysfs(indio_dev); 900 iio_device_unregister_sysfs(indio_dev);
901error_unreg_debugfs:
902 iio_device_unregister_debugfs(indio_dev);
768error_ret: 903error_ret:
769 return ret; 904 return ret;
770} 905}