usb: dwc3: gadget: allow testmodes changes via debugfs
This is very useful for low level Link Testing where we might not have a USB Host stack, only a scope to verify signal integrity. Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
Родитель
04a9bfcd50
Коммит
080d921fe7
|
@ -46,6 +46,8 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <linux/usb/ch9.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "gadget.h"
|
||||
#include "io.h"
|
||||
|
@ -464,6 +466,89 @@ static const struct file_operations dwc3_mode_fops = {
|
|||
.release = single_release,
|
||||
};
|
||||
|
||||
static int dwc3_testmode_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_DCTL);
|
||||
reg &= DWC3_DCTL_TSTCTRL_MASK;
|
||||
reg >>= 1;
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
|
||||
switch (reg) {
|
||||
case 0:
|
||||
seq_printf(s, "no test\n");
|
||||
break;
|
||||
case TEST_J:
|
||||
seq_printf(s, "test_j\n");
|
||||
break;
|
||||
case TEST_K:
|
||||
seq_printf(s, "test_k\n");
|
||||
break;
|
||||
case TEST_SE0_NAK:
|
||||
seq_printf(s, "test_se0_nak\n");
|
||||
break;
|
||||
case TEST_PACKET:
|
||||
seq_printf(s, "test_packet\n");
|
||||
break;
|
||||
case TEST_FORCE_EN:
|
||||
seq_printf(s, "test_force_enable\n");
|
||||
break;
|
||||
default:
|
||||
seq_printf(s, "UNKNOWN %d\n", reg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dwc3_testmode_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, dwc3_testmode_show, inode->i_private);
|
||||
}
|
||||
|
||||
static ssize_t dwc3_testmode_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 testmode = 0;
|
||||
char buf[32];
|
||||
|
||||
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
|
||||
return -EFAULT;
|
||||
|
||||
if (!strncmp(buf, "test_j", 6))
|
||||
testmode = TEST_J;
|
||||
else if (!strncmp(buf, "test_k", 6))
|
||||
testmode = TEST_K;
|
||||
else if (!strncmp(buf, "test_se0_nak", 13))
|
||||
testmode = TEST_SE0_NAK;
|
||||
else if (!strncmp(buf, "test_packet", 12))
|
||||
testmode = TEST_PACKET;
|
||||
else if (!strncmp(buf, "test_force_enable", 18))
|
||||
testmode = TEST_FORCE_EN;
|
||||
else
|
||||
testmode = 0;
|
||||
|
||||
spin_lock_irqsave(&dwc->lock, flags);
|
||||
dwc3_gadget_set_test_mode(dwc, testmode);
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations dwc3_testmode_fops = {
|
||||
.open = dwc3_testmode_open,
|
||||
.write = dwc3_testmode_write,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
int __devinit dwc3_debugfs_init(struct dwc3 *dwc)
|
||||
{
|
||||
struct dentry *root;
|
||||
|
@ -492,6 +577,13 @@ int __devinit dwc3_debugfs_init(struct dwc3 *dwc)
|
|||
goto err1;
|
||||
}
|
||||
|
||||
file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root,
|
||||
dwc, &dwc3_testmode_fops);
|
||||
if (IS_ERR(file)) {
|
||||
ret = PTR_ERR(file);
|
||||
goto err1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err1:
|
||||
|
|
Загрузка…
Ссылка в новой задаче