diff options
author | Felipe Balbi <balbi@ti.com> | 2011-10-17 01:50:39 -0400 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2011-12-12 04:48:15 -0500 |
commit | 0b9fe32deece53c9bc6d1e6d17a85ef1eb2e294b (patch) | |
tree | 8f5be7d34c7e014e33493bc27b9e96899be671e7 /drivers/usb/dwc3 | |
parent | f96a6ec1db1ac730b5a031f2c2f7fcc6b07459d8 (diff) |
usb: dwc3: debugfs: add support for changing port mode
This makes testing a lot easier when trying to
switch between host and device modes.
Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/dwc3')
-rw-r--r-- | drivers/usb/dwc3/core.h | 1 | ||||
-rw-r--r-- | drivers/usb/dwc3/debugfs.c | 82 |
2 files changed, 83 insertions, 0 deletions
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 513a7391099f..6f1e8c98d78d 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h | |||
@@ -154,6 +154,7 @@ | |||
154 | #define DWC3_GCTL_CLK_PIPEHALF (2) | 154 | #define DWC3_GCTL_CLK_PIPEHALF (2) |
155 | #define DWC3_GCTL_CLK_MASK (3) | 155 | #define DWC3_GCTL_CLK_MASK (3) |
156 | 156 | ||
157 | #define DWC3_GCTL_PRTCAP(n) (((n) & (3 << 12)) >> 12) | ||
157 | #define DWC3_GCTL_PRTCAPDIR(n) (n << 12) | 158 | #define DWC3_GCTL_PRTCAPDIR(n) (n << 12) |
158 | #define DWC3_GCTL_PRTCAP_HOST 1 | 159 | #define DWC3_GCTL_PRTCAP_HOST 1 |
159 | #define DWC3_GCTL_PRTCAP_DEVICE 2 | 160 | #define DWC3_GCTL_PRTCAP_DEVICE 2 |
diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index da1ad77d8d51..fc49334a01cf 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c | |||
@@ -405,6 +405,80 @@ static const struct file_operations dwc3_regdump_fops = { | |||
405 | .release = single_release, | 405 | .release = single_release, |
406 | }; | 406 | }; |
407 | 407 | ||
408 | static int dwc3_mode_show(struct seq_file *s, void *unused) | ||
409 | { | ||
410 | struct dwc3 *dwc = s->private; | ||
411 | unsigned long flags; | ||
412 | u32 reg; | ||
413 | |||
414 | spin_lock_irqsave(&dwc->lock, flags); | ||
415 | reg = dwc3_readl(dwc->regs, DWC3_GCTL); | ||
416 | spin_unlock_irqrestore(&dwc->lock, flags); | ||
417 | |||
418 | switch (DWC3_GCTL_PRTCAP(reg)) { | ||
419 | case DWC3_GCTL_PRTCAP_HOST: | ||
420 | seq_printf(s, "host\n"); | ||
421 | break; | ||
422 | case DWC3_GCTL_PRTCAP_DEVICE: | ||
423 | seq_printf(s, "device\n"); | ||
424 | break; | ||
425 | case DWC3_GCTL_PRTCAP_OTG: | ||
426 | seq_printf(s, "OTG\n"); | ||
427 | break; | ||
428 | default: | ||
429 | seq_printf(s, "UNKNOWN %08x\n", DWC3_GCTL_PRTCAP(reg)); | ||
430 | } | ||
431 | |||
432 | return 0; | ||
433 | } | ||
434 | |||
435 | static int dwc3_mode_open(struct inode *inode, struct file *file) | ||
436 | { | ||
437 | return single_open(file, dwc3_mode_show, inode->i_private); | ||
438 | } | ||
439 | |||
440 | static ssize_t dwc3_mode_write(struct file *file, | ||
441 | const char __user *ubuf, size_t count, loff_t *ppos) | ||
442 | { | ||
443 | struct seq_file *s = file->private_data; | ||
444 | struct dwc3 *dwc = s->private; | ||
445 | unsigned long flags; | ||
446 | u32 reg; | ||
447 | char buf[32]; | ||
448 | |||
449 | if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) | ||
450 | return -EFAULT; | ||
451 | |||
452 | spin_lock_irqsave(&dwc->lock, flags); | ||
453 | reg = dwc3_readl(dwc->regs, DWC3_GCTL); | ||
454 | spin_unlock_irqrestore(&dwc->lock, flags); | ||
455 | |||
456 | reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); | ||
457 | |||
458 | if (!strncmp(buf, "host", 4)) | ||
459 | reg |= DWC3_GCTL_PRTCAP(DWC3_GCTL_PRTCAP_HOST); | ||
460 | |||
461 | if (!strncmp(buf, "device", 6)) | ||
462 | reg |= DWC3_GCTL_PRTCAP(DWC3_GCTL_PRTCAP_DEVICE); | ||
463 | |||
464 | if (!strncmp(buf, "otg", 3)) | ||
465 | reg |= DWC3_GCTL_PRTCAP(DWC3_GCTL_PRTCAP_OTG); | ||
466 | |||
467 | spin_lock_irqsave(&dwc->lock, flags); | ||
468 | dwc3_writel(dwc->regs, DWC3_GCTL, reg); | ||
469 | spin_unlock_irqrestore(&dwc->lock, flags); | ||
470 | |||
471 | return count; | ||
472 | } | ||
473 | |||
474 | static const struct file_operations dwc3_mode_fops = { | ||
475 | .open = dwc3_mode_open, | ||
476 | .write = dwc3_mode_write, | ||
477 | .read = seq_read, | ||
478 | .llseek = seq_lseek, | ||
479 | .release = single_release, | ||
480 | }; | ||
481 | |||
408 | int __devinit dwc3_debugfs_init(struct dwc3 *dwc) | 482 | int __devinit dwc3_debugfs_init(struct dwc3 *dwc) |
409 | { | 483 | { |
410 | struct dentry *root; | 484 | struct dentry *root; |
@@ -425,6 +499,14 @@ int __devinit dwc3_debugfs_init(struct dwc3 *dwc) | |||
425 | ret = PTR_ERR(file); | 499 | ret = PTR_ERR(file); |
426 | goto err1; | 500 | goto err1; |
427 | } | 501 | } |
502 | |||
503 | file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root, | ||
504 | dwc, &dwc3_mode_fops); | ||
505 | if (IS_ERR(file)) { | ||
506 | ret = PTR_ERR(file); | ||
507 | goto err1; | ||
508 | } | ||
509 | |||
428 | return 0; | 510 | return 0; |
429 | 511 | ||
430 | err1: | 512 | err1: |