diff options
| author | Felipe Balbi <balbi@ti.com> | 2011-10-17 08:50:39 +0300 | 
|---|---|---|
| committer | Felipe Balbi <balbi@ti.com> | 2011-12-12 11:48:15 +0200 | 
| commit | 0b9fe32deece53c9bc6d1e6d17a85ef1eb2e294b (patch) | |
| tree | 8f5be7d34c7e014e33493bc27b9e96899be671e7 | |
| parent | f96a6ec1db1ac730b5a031f2c2f7fcc6b07459d8 (diff) | |
| download | olio-linux-3.10-0b9fe32deece53c9bc6d1e6d17a85ef1eb2e294b.tar.xz olio-linux-3.10-0b9fe32deece53c9bc6d1e6d17a85ef1eb2e294b.zip  | |
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>
| -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 513a7391099..6f1e8c98d78 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -154,6 +154,7 @@  #define DWC3_GCTL_CLK_PIPEHALF	(2)  #define DWC3_GCTL_CLK_MASK	(3) +#define DWC3_GCTL_PRTCAP(n)	(((n) & (3 << 12)) >> 12)  #define DWC3_GCTL_PRTCAPDIR(n)	(n << 12)  #define DWC3_GCTL_PRTCAP_HOST	1  #define DWC3_GCTL_PRTCAP_DEVICE	2 diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index da1ad77d8d5..fc49334a01c 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 = {  	.release		= single_release,  }; +static int dwc3_mode_show(struct seq_file *s, void *unused) +{ +	struct dwc3		*dwc = s->private; +	unsigned long		flags; +	u32			reg; + +	spin_lock_irqsave(&dwc->lock, flags); +	reg = dwc3_readl(dwc->regs, DWC3_GCTL); +	spin_unlock_irqrestore(&dwc->lock, flags); + +	switch (DWC3_GCTL_PRTCAP(reg)) { +	case DWC3_GCTL_PRTCAP_HOST: +		seq_printf(s, "host\n"); +		break; +	case DWC3_GCTL_PRTCAP_DEVICE: +		seq_printf(s, "device\n"); +		break; +	case DWC3_GCTL_PRTCAP_OTG: +		seq_printf(s, "OTG\n"); +		break; +	default: +		seq_printf(s, "UNKNOWN %08x\n", DWC3_GCTL_PRTCAP(reg)); +	} + +	return 0; +} + +static int dwc3_mode_open(struct inode *inode, struct file *file) +{ +	return single_open(file, dwc3_mode_show, inode->i_private); +} + +static ssize_t dwc3_mode_write(struct file *file, +		const char __user *ubuf, size_t count, loff_t *ppos) +{ +	struct seq_file		*s = file->private_data; +	struct dwc3		*dwc = s->private; +	unsigned long		flags; +	u32			reg; +	char			buf[32]; + +	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) +		return -EFAULT; + +	spin_lock_irqsave(&dwc->lock, flags); +	reg = dwc3_readl(dwc->regs, DWC3_GCTL); +	spin_unlock_irqrestore(&dwc->lock, flags); + +	reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); + +	if (!strncmp(buf, "host", 4)) +		reg |= DWC3_GCTL_PRTCAP(DWC3_GCTL_PRTCAP_HOST); + +	if (!strncmp(buf, "device", 6)) +		reg |= DWC3_GCTL_PRTCAP(DWC3_GCTL_PRTCAP_DEVICE); + +	if (!strncmp(buf, "otg", 3)) +		reg |= DWC3_GCTL_PRTCAP(DWC3_GCTL_PRTCAP_OTG); + +	spin_lock_irqsave(&dwc->lock, flags); +	dwc3_writel(dwc->regs, DWC3_GCTL, reg); +	spin_unlock_irqrestore(&dwc->lock, flags); + +	return count; +} + +static const struct file_operations dwc3_mode_fops = { +	.open			= dwc3_mode_open, +	.write			= dwc3_mode_write, +	.read			= seq_read, +	.llseek			= seq_lseek, +	.release		= single_release, +}; +  int __devinit dwc3_debugfs_init(struct dwc3 *dwc)  {  	struct dentry		*root; @@ -425,6 +499,14 @@ int __devinit dwc3_debugfs_init(struct dwc3 *dwc)  		ret = PTR_ERR(file);  		goto err1;  	} + +	file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root, +			dwc, &dwc3_mode_fops); +	if (IS_ERR(file)) { +		ret = PTR_ERR(file); +		goto err1; +	} +  	return 0;  err1:  |