usb: gadget: udc: renesas_usb3: add debugfs to set the b-device mode

This patch adds debugfs to set the "b-device" mode for using a board
which is not connected to the ID pin (e.g. CN11 on Salvator-X).
If we want to use peripheral mode on such a board, we have to disable
VBUS output first. So, this patch can set such a mode as the following:

 # mount -t debugfs none /sys/kernel/debug
 # modprobe renesas_usb3
 # modprobe g_mass_storage file=/dev/shm/test.bin
 # echo 1 > /sys/kernel/debug/ee020000.usb/b_device

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
This commit is contained in:
Yoshihiro Shimoda 2017-08-04 11:16:56 +09:00 committed by Felipe Balbi
parent 7d343a6a88
commit 43ba968b00
1 changed files with 76 additions and 2 deletions

View File

@ -8,6 +8,7 @@
* the Free Software Foundation; version 2 of the License.
*/
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
@ -20,6 +21,7 @@
#include <linux/pm_runtime.h>
#include <linux/sizes.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
@ -347,6 +349,7 @@ struct renesas_usb3 {
bool workaround_for_vbus;
bool extcon_host; /* check id and set EXTCON_USB_HOST */
bool extcon_usb; /* check vbus and set EXTCON_USB */
bool forced_b_device;
};
#define gadget_to_renesas_usb3(_gadget) \
@ -663,7 +666,9 @@ static void usb3_mode_config(struct renesas_usb3 *usb3, bool host, bool a_dev)
spin_lock_irqsave(&usb3->lock, flags);
usb3_set_mode(usb3, host);
usb3_vbus_out(usb3, a_dev);
if (!host && a_dev) /* for A-Peripheral */
/* for A-Peripheral or forced B-device mode */
if ((!host && a_dev) ||
(usb3->workaround_for_vbus && usb3->forced_b_device))
usb3_connect(usb3);
spin_unlock_irqrestore(&usb3->lock, flags);
}
@ -677,7 +682,7 @@ static void usb3_check_id(struct renesas_usb3 *usb3)
{
usb3->extcon_host = usb3_is_a_device(usb3);
if (usb3->extcon_host)
if (usb3->extcon_host && !usb3->forced_b_device)
usb3_mode_config(usb3, true, true);
else
usb3_mode_config(usb3, false, false);
@ -2272,6 +2277,9 @@ static ssize_t role_store(struct device *dev, struct device_attribute *attr,
if (!usb3->driver)
return -ENODEV;
if (usb3->forced_b_device)
return -EBUSY;
if (!strncmp(buf, "host", strlen("host")))
new_mode_is_host = true;
else if (!strncmp(buf, "peripheral", strlen("peripheral")))
@ -2299,6 +2307,70 @@ static ssize_t role_show(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR_RW(role);
static int renesas_usb3_b_device_show(struct seq_file *s, void *unused)
{
struct renesas_usb3 *usb3 = s->private;
seq_printf(s, "%d\n", usb3->forced_b_device);
return 0;
}
static int renesas_usb3_b_device_open(struct inode *inode, struct file *file)
{
return single_open(file, renesas_usb3_b_device_show, inode->i_private);
}
static ssize_t renesas_usb3_b_device_write(struct file *file,
const char __user *ubuf,
size_t count, loff_t *ppos)
{
struct seq_file *s = file->private_data;
struct renesas_usb3 *usb3 = s->private;
char buf[32];
if (!usb3->driver)
return -ENODEV;
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
return -EFAULT;
if (!strncmp(buf, "1", 1))
usb3->forced_b_device = true;
else
usb3->forced_b_device = false;
/* Let this driver call usb3_connect() anyway */
usb3_check_id(usb3);
return count;
}
static const struct file_operations renesas_usb3_b_device_fops = {
.open = renesas_usb3_b_device_open,
.write = renesas_usb3_b_device_write,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static void renesas_usb3_debugfs_init(struct renesas_usb3 *usb3,
struct device *dev)
{
struct dentry *root, *file;
root = debugfs_create_dir(dev_name(dev), NULL);
if (IS_ERR_OR_NULL(root)) {
dev_info(dev, "%s: Can't create the root\n", __func__);
return;
}
file = debugfs_create_file("b_device", 0644, root, usb3,
&renesas_usb3_b_device_fops);
if (!file)
dev_info(dev, "%s: Can't create debugfs mode\n", __func__);
}
/*------- platform_driver ------------------------------------------------*/
static int renesas_usb3_remove(struct platform_device *pdev)
{
@ -2518,6 +2590,8 @@ static int renesas_usb3_probe(struct platform_device *pdev)
usb3->workaround_for_vbus = priv->workaround_for_vbus;
renesas_usb3_debugfs_init(usb3, &pdev->dev);
dev_info(&pdev->dev, "probed\n");
return 0;