diff options
Diffstat (limited to 'drivers/usb/chipidea/debug.c')
| -rw-r--r-- | drivers/usb/chipidea/debug.c | 233 |
1 files changed, 120 insertions, 113 deletions
diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c index 96d899aee473..e72c43615d77 100644 --- a/drivers/usb/chipidea/debug.c +++ b/drivers/usb/chipidea/debug.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 #include <linux/kernel.h> #include <linux/device.h> #include <linux/types.h> @@ -7,13 +8,17 @@ #include <linux/uaccess.h> #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> +#include <linux/usb/phy.h> +#include <linux/usb/otg.h> +#include <linux/usb/otg-fsm.h> +#include <linux/usb/chipidea.h> #include "ci.h" #include "udc.h" #include "bits.h" -#include "debug.h" +#include "otg.h" -/** +/* * ci_device_show: prints information about device capabilities and status */ static int ci_device_show(struct seq_file *s, void *data) @@ -40,20 +45,9 @@ static int ci_device_show(struct seq_file *s, void *data) return 0; } +DEFINE_SHOW_ATTRIBUTE(ci_device); -static int ci_device_open(struct inode *inode, struct file *file) -{ - return single_open(file, ci_device_show, inode->i_private); -} - -static const struct file_operations ci_device_fops = { - .open = ci_device_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/** +/* * ci_port_test_show: reads port test mode */ static int ci_port_test_show(struct seq_file *s, void *data) @@ -62,16 +56,18 @@ static int ci_port_test_show(struct seq_file *s, void *data) unsigned long flags; unsigned mode; + pm_runtime_get_sync(ci->dev); spin_lock_irqsave(&ci->lock, flags); mode = hw_port_test_get(ci); spin_unlock_irqrestore(&ci->lock, flags); + pm_runtime_put_sync(ci->dev); seq_printf(s, "mode = %u\n", mode); return 0; } -/** +/* * ci_port_test_write: writes port test mode */ static ssize_t ci_port_test_write(struct file *file, const char __user *ubuf, @@ -84,15 +80,24 @@ static ssize_t ci_port_test_write(struct file *file, const char __user *ubuf, char buf[32]; int ret; - if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) + count = min_t(size_t, sizeof(buf) - 1, count); + if (copy_from_user(buf, ubuf, count)) return -EFAULT; + /* sscanf requires a zero terminated string */ + buf[count] = '\0'; + if (sscanf(buf, "%u", &mode) != 1) return -EINVAL; + if (mode > 255) + return -EBADRQC; + + pm_runtime_get_sync(ci->dev); spin_lock_irqsave(&ci->lock, flags); ret = hw_port_test_set(ci, mode); spin_unlock_irqrestore(&ci->lock, flags); + pm_runtime_put_sync(ci->dev); return ret ? ret : count; } @@ -110,7 +115,7 @@ static const struct file_operations ci_port_test_fops = { .release = single_release, }; -/** +/* * ci_qheads_show: DMA contents of all queue heads */ static int ci_qheads_show(struct seq_file *s, void *data) @@ -140,27 +145,15 @@ static int ci_qheads_show(struct seq_file *s, void *data) return 0; } +DEFINE_SHOW_ATTRIBUTE(ci_qheads); -static int ci_qheads_open(struct inode *inode, struct file *file) -{ - return single_open(file, ci_qheads_show, inode->i_private); -} - -static const struct file_operations ci_qheads_fops = { - .open = ci_qheads_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/** +/* * ci_requests_show: DMA contents of all requests currently queued (all endpts) */ static int ci_requests_show(struct seq_file *s, void *data) { struct ci_hdrc *ci = s->private; unsigned long flags; - struct list_head *ptr = NULL; struct ci_hw_req *req = NULL; struct td_node *node, *tmpnode; unsigned i, j, qsize = sizeof(struct ci_hw_td)/sizeof(u32); @@ -172,9 +165,7 @@ static int ci_requests_show(struct seq_file *s, void *data) spin_lock_irqsave(&ci->lock, flags); for (i = 0; i < ci->hw_ep_max; i++) - list_for_each(ptr, &ci->ci_hw_ep[i].qh.queue) { - req = list_entry(ptr, struct ci_hw_req, queue); - + list_for_each_entry(req, &ci->ci_hw_ep[i].qh.queue, queue) { list_for_each_entry_safe(node, tmpnode, &req->tds, td) { seq_printf(s, "EP=%02i: TD=%08X %s\n", i % (ci->hw_ep_max / 2), @@ -191,67 +182,103 @@ static int ci_requests_show(struct seq_file *s, void *data) return 0; } +DEFINE_SHOW_ATTRIBUTE(ci_requests); -static int ci_requests_open(struct inode *inode, struct file *file) +static int ci_otg_show(struct seq_file *s, void *unused) { - return single_open(file, ci_requests_show, inode->i_private); -} + struct ci_hdrc *ci = s->private; + struct otg_fsm *fsm; -static const struct file_operations ci_requests_fops = { - .open = ci_requests_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; + if (!ci || !ci_otg_is_fsm_mode(ci)) + return 0; -static int ci_role_show(struct seq_file *s, void *data) -{ - struct ci_hdrc *ci = s->private; + fsm = &ci->fsm; + + /* ------ State ----- */ + seq_printf(s, "OTG state: %s\n\n", + usb_otg_state_string(ci->otg.state)); + + /* ------ State Machine Variables ----- */ + seq_printf(s, "a_bus_drop: %d\n", fsm->a_bus_drop); + + seq_printf(s, "a_bus_req: %d\n", fsm->a_bus_req); + + seq_printf(s, "a_srp_det: %d\n", fsm->a_srp_det); + + seq_printf(s, "a_vbus_vld: %d\n", fsm->a_vbus_vld); - seq_printf(s, "%s\n", ci_role(ci)->name); + seq_printf(s, "b_conn: %d\n", fsm->b_conn); + + seq_printf(s, "adp_change: %d\n", fsm->adp_change); + + seq_printf(s, "power_up: %d\n", fsm->power_up); + + seq_printf(s, "a_bus_resume: %d\n", fsm->a_bus_resume); + + seq_printf(s, "a_bus_suspend: %d\n", fsm->a_bus_suspend); + + seq_printf(s, "a_conn: %d\n", fsm->a_conn); + + seq_printf(s, "b_bus_req: %d\n", fsm->b_bus_req); + + seq_printf(s, "b_bus_suspend: %d\n", fsm->b_bus_suspend); + + seq_printf(s, "b_se0_srp: %d\n", fsm->b_se0_srp); + + seq_printf(s, "b_ssend_srp: %d\n", fsm->b_ssend_srp); + + seq_printf(s, "b_sess_vld: %d\n", fsm->b_sess_vld); + + seq_printf(s, "b_srp_done: %d\n", fsm->b_srp_done); + + seq_printf(s, "drv_vbus: %d\n", fsm->drv_vbus); + + seq_printf(s, "loc_conn: %d\n", fsm->loc_conn); + + seq_printf(s, "loc_sof: %d\n", fsm->loc_sof); + + seq_printf(s, "adp_prb: %d\n", fsm->adp_prb); + + seq_printf(s, "id: %d\n", fsm->id); + + seq_printf(s, "protocol: %d\n", fsm->protocol); return 0; } +DEFINE_SHOW_ATTRIBUTE(ci_otg); -static ssize_t ci_role_write(struct file *file, const char __user *ubuf, - size_t count, loff_t *ppos) +static int ci_registers_show(struct seq_file *s, void *unused) { - struct seq_file *s = file->private_data; struct ci_hdrc *ci = s->private; - enum ci_role role; - char buf[8]; - int ret; + u32 tmp_reg; - if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) - return -EFAULT; + if (!ci || ci->in_lpm) + return -EPERM; - for (role = CI_ROLE_HOST; role < CI_ROLE_END; role++) - if (ci->roles[role] && - !strncmp(buf, ci->roles[role]->name, - strlen(ci->roles[role]->name))) - break; + /* ------ Registers ----- */ + tmp_reg = hw_read_intr_enable(ci); + seq_printf(s, "USBINTR reg: %08x\n", tmp_reg); - if (role == CI_ROLE_END || role == ci->role) - return -EINVAL; + tmp_reg = hw_read_intr_status(ci); + seq_printf(s, "USBSTS reg: %08x\n", tmp_reg); - ci_role_stop(ci); - ret = ci_role_start(ci, role); + tmp_reg = hw_read(ci, OP_USBMODE, ~0); + seq_printf(s, "USBMODE reg: %08x\n", tmp_reg); - return ret ? ret : count; -} + tmp_reg = hw_read(ci, OP_USBCMD, ~0); + seq_printf(s, "USBCMD reg: %08x\n", tmp_reg); -static int ci_role_open(struct inode *inode, struct file *file) -{ - return single_open(file, ci_role_show, inode->i_private); -} + tmp_reg = hw_read(ci, OP_PORTSC, ~0); + seq_printf(s, "PORTSC reg: %08x\n", tmp_reg); -static const struct file_operations ci_role_fops = { - .open = ci_role_open, - .write = ci_role_write, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; + if (ci->is_otg) { + tmp_reg = hw_read_otgsc(ci, ~0); + seq_printf(s, "OTGSC reg: %08x\n", tmp_reg); + } + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(ci_registers); /** * dbg_create_files: initializes the attribute interface @@ -259,41 +286,21 @@ static const struct file_operations ci_role_fops = { * * This function returns an error code */ -int dbg_create_files(struct ci_hdrc *ci) +void dbg_create_files(struct ci_hdrc *ci) { - struct dentry *dent; - - ci->debugfs = debugfs_create_dir(dev_name(ci->dev), NULL); - if (!ci->debugfs) - return -ENOMEM; - - dent = debugfs_create_file("device", S_IRUGO, ci->debugfs, ci, - &ci_device_fops); - if (!dent) - goto err; - - dent = debugfs_create_file("port_test", S_IRUGO | S_IWUSR, ci->debugfs, - ci, &ci_port_test_fops); - if (!dent) - goto err; - - dent = debugfs_create_file("qheads", S_IRUGO, ci->debugfs, ci, - &ci_qheads_fops); - if (!dent) - goto err; - - dent = debugfs_create_file("requests", S_IRUGO, ci->debugfs, ci, - &ci_requests_fops); - if (!dent) - goto err; - - dent = debugfs_create_file("role", S_IRUGO | S_IWUSR, ci->debugfs, ci, - &ci_role_fops); - if (dent) - return 0; -err: - debugfs_remove_recursive(ci->debugfs); - return -ENOMEM; + struct dentry *dir; + + dir = debugfs_create_dir(dev_name(ci->dev), usb_debug_root); + + debugfs_create_file("device", S_IRUGO, dir, ci, &ci_device_fops); + debugfs_create_file("port_test", S_IRUGO | S_IWUSR, dir, ci, &ci_port_test_fops); + debugfs_create_file("qheads", S_IRUGO, dir, ci, &ci_qheads_fops); + debugfs_create_file("requests", S_IRUGO, dir, ci, &ci_requests_fops); + + if (ci_otg_is_fsm_mode(ci)) + debugfs_create_file("otg", S_IRUGO, dir, ci, &ci_otg_fops); + + debugfs_create_file("registers", S_IRUGO, dir, ci, &ci_registers_fops); } /** @@ -302,5 +309,5 @@ err: */ void dbg_remove_files(struct ci_hdrc *ci) { - debugfs_remove_recursive(ci->debugfs); + debugfs_lookup_and_remove(dev_name(ci->dev), usb_debug_root); } |
