|
27 | 27 | #include <linux/err.h> |
28 | 28 | #include <linux/slab.h> |
29 | 29 | #include <linux/device.h> |
| 30 | +#include <linux/debugfs.h> |
| 31 | +#include <linux/seq_file.h> |
30 | 32 |
|
31 | 33 | #define MAX_PWMS 1024 |
32 | 34 |
|
@@ -338,3 +340,91 @@ void pwm_disable(struct pwm_device *pwm) |
338 | 340 | pwm->chip->ops->disable(pwm->chip, pwm); |
339 | 341 | } |
340 | 342 | EXPORT_SYMBOL_GPL(pwm_disable); |
| 343 | + |
| 344 | +#ifdef CONFIG_DEBUG_FS |
| 345 | +static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s) |
| 346 | +{ |
| 347 | + unsigned int i; |
| 348 | + |
| 349 | + for (i = 0; i < chip->npwm; i++) { |
| 350 | + struct pwm_device *pwm = &chip->pwms[i]; |
| 351 | + |
| 352 | + seq_printf(s, " pwm-%-3d (%-20.20s):", i, pwm->label); |
| 353 | + |
| 354 | + if (test_bit(PWMF_REQUESTED, &pwm->flags)) |
| 355 | + seq_printf(s, " requested"); |
| 356 | + |
| 357 | + if (test_bit(PWMF_ENABLED, &pwm->flags)) |
| 358 | + seq_printf(s, " enabled"); |
| 359 | + |
| 360 | + seq_printf(s, "\n"); |
| 361 | + } |
| 362 | +} |
| 363 | + |
| 364 | +static void *pwm_seq_start(struct seq_file *s, loff_t *pos) |
| 365 | +{ |
| 366 | + mutex_lock(&pwm_lock); |
| 367 | + s->private = ""; |
| 368 | + |
| 369 | + return seq_list_start(&pwm_chips, *pos); |
| 370 | +} |
| 371 | + |
| 372 | +static void *pwm_seq_next(struct seq_file *s, void *v, loff_t *pos) |
| 373 | +{ |
| 374 | + s->private = "\n"; |
| 375 | + |
| 376 | + return seq_list_next(v, &pwm_chips, pos); |
| 377 | +} |
| 378 | + |
| 379 | +static void pwm_seq_stop(struct seq_file *s, void *v) |
| 380 | +{ |
| 381 | + mutex_unlock(&pwm_lock); |
| 382 | +} |
| 383 | + |
| 384 | +static int pwm_seq_show(struct seq_file *s, void *v) |
| 385 | +{ |
| 386 | + struct pwm_chip *chip = list_entry(v, struct pwm_chip, list); |
| 387 | + |
| 388 | + seq_printf(s, "%s%s/%s, %d PWM device%s\n", (char *)s->private, |
| 389 | + chip->dev->bus ? chip->dev->bus->name : "no-bus", |
| 390 | + dev_name(chip->dev), chip->npwm, |
| 391 | + (chip->npwm != 1) ? "s" : ""); |
| 392 | + |
| 393 | + if (chip->ops->dbg_show) |
| 394 | + chip->ops->dbg_show(chip, s); |
| 395 | + else |
| 396 | + pwm_dbg_show(chip, s); |
| 397 | + |
| 398 | + return 0; |
| 399 | +} |
| 400 | + |
| 401 | +static const struct seq_operations pwm_seq_ops = { |
| 402 | + .start = pwm_seq_start, |
| 403 | + .next = pwm_seq_next, |
| 404 | + .stop = pwm_seq_stop, |
| 405 | + .show = pwm_seq_show, |
| 406 | +}; |
| 407 | + |
| 408 | +static int pwm_seq_open(struct inode *inode, struct file *file) |
| 409 | +{ |
| 410 | + return seq_open(file, &pwm_seq_ops); |
| 411 | +} |
| 412 | + |
| 413 | +static const struct file_operations pwm_debugfs_ops = { |
| 414 | + .owner = THIS_MODULE, |
| 415 | + .open = pwm_seq_open, |
| 416 | + .read = seq_read, |
| 417 | + .llseek = seq_lseek, |
| 418 | + .release = seq_release, |
| 419 | +}; |
| 420 | + |
| 421 | +static int __init pwm_debugfs_init(void) |
| 422 | +{ |
| 423 | + debugfs_create_file("pwm", S_IFREG | S_IRUGO, NULL, NULL, |
| 424 | + &pwm_debugfs_ops); |
| 425 | + |
| 426 | + return 0; |
| 427 | +} |
| 428 | + |
| 429 | +subsys_initcall(pwm_debugfs_init); |
| 430 | +#endif /* CONFIG_DEBUG_FS */ |
0 commit comments