18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include <linux/kernel.h>
38c2ecf20Sopenharmony_ci#include <linux/device.h>
48c2ecf20Sopenharmony_ci#include <linux/types.h>
58c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
68c2ecf20Sopenharmony_ci#include <linux/debugfs.h>
78c2ecf20Sopenharmony_ci#include <linux/seq_file.h>
88c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
98c2ecf20Sopenharmony_ci#include <linux/usb/ch9.h>
108c2ecf20Sopenharmony_ci#include <linux/usb/gadget.h>
118c2ecf20Sopenharmony_ci#include <linux/usb/phy.h>
128c2ecf20Sopenharmony_ci#include <linux/usb/otg.h>
138c2ecf20Sopenharmony_ci#include <linux/usb/otg-fsm.h>
148c2ecf20Sopenharmony_ci#include <linux/usb/chipidea.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include "ci.h"
178c2ecf20Sopenharmony_ci#include "udc.h"
188c2ecf20Sopenharmony_ci#include "bits.h"
198c2ecf20Sopenharmony_ci#include "otg.h"
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci/*
228c2ecf20Sopenharmony_ci * ci_device_show: prints information about device capabilities and status
238c2ecf20Sopenharmony_ci */
248c2ecf20Sopenharmony_cistatic int ci_device_show(struct seq_file *s, void *data)
258c2ecf20Sopenharmony_ci{
268c2ecf20Sopenharmony_ci	struct ci_hdrc *ci = s->private;
278c2ecf20Sopenharmony_ci	struct usb_gadget *gadget = &ci->gadget;
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci	seq_printf(s, "speed             = %d\n", gadget->speed);
308c2ecf20Sopenharmony_ci	seq_printf(s, "max_speed         = %d\n", gadget->max_speed);
318c2ecf20Sopenharmony_ci	seq_printf(s, "is_otg            = %d\n", gadget->is_otg);
328c2ecf20Sopenharmony_ci	seq_printf(s, "is_a_peripheral   = %d\n", gadget->is_a_peripheral);
338c2ecf20Sopenharmony_ci	seq_printf(s, "b_hnp_enable      = %d\n", gadget->b_hnp_enable);
348c2ecf20Sopenharmony_ci	seq_printf(s, "a_hnp_support     = %d\n", gadget->a_hnp_support);
358c2ecf20Sopenharmony_ci	seq_printf(s, "a_alt_hnp_support = %d\n", gadget->a_alt_hnp_support);
368c2ecf20Sopenharmony_ci	seq_printf(s, "name              = %s\n",
378c2ecf20Sopenharmony_ci		   (gadget->name ? gadget->name : ""));
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	if (!ci->driver)
408c2ecf20Sopenharmony_ci		return 0;
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	seq_printf(s, "gadget function   = %s\n",
438c2ecf20Sopenharmony_ci		       (ci->driver->function ? ci->driver->function : ""));
448c2ecf20Sopenharmony_ci	seq_printf(s, "gadget max speed  = %d\n", ci->driver->max_speed);
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	return 0;
478c2ecf20Sopenharmony_ci}
488c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(ci_device);
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci/*
518c2ecf20Sopenharmony_ci * ci_port_test_show: reads port test mode
528c2ecf20Sopenharmony_ci */
538c2ecf20Sopenharmony_cistatic int ci_port_test_show(struct seq_file *s, void *data)
548c2ecf20Sopenharmony_ci{
558c2ecf20Sopenharmony_ci	struct ci_hdrc *ci = s->private;
568c2ecf20Sopenharmony_ci	unsigned long flags;
578c2ecf20Sopenharmony_ci	unsigned mode;
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	pm_runtime_get_sync(ci->dev);
608c2ecf20Sopenharmony_ci	spin_lock_irqsave(&ci->lock, flags);
618c2ecf20Sopenharmony_ci	mode = hw_port_test_get(ci);
628c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&ci->lock, flags);
638c2ecf20Sopenharmony_ci	pm_runtime_put_sync(ci->dev);
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	seq_printf(s, "mode = %u\n", mode);
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	return 0;
688c2ecf20Sopenharmony_ci}
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci/*
718c2ecf20Sopenharmony_ci * ci_port_test_write: writes port test mode
728c2ecf20Sopenharmony_ci */
738c2ecf20Sopenharmony_cistatic ssize_t ci_port_test_write(struct file *file, const char __user *ubuf,
748c2ecf20Sopenharmony_ci				  size_t count, loff_t *ppos)
758c2ecf20Sopenharmony_ci{
768c2ecf20Sopenharmony_ci	struct seq_file *s = file->private_data;
778c2ecf20Sopenharmony_ci	struct ci_hdrc *ci = s->private;
788c2ecf20Sopenharmony_ci	unsigned long flags;
798c2ecf20Sopenharmony_ci	unsigned mode;
808c2ecf20Sopenharmony_ci	char buf[32];
818c2ecf20Sopenharmony_ci	int ret;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	count = min_t(size_t, sizeof(buf) - 1, count);
848c2ecf20Sopenharmony_ci	if (copy_from_user(buf, ubuf, count))
858c2ecf20Sopenharmony_ci		return -EFAULT;
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	/* sscanf requires a zero terminated string */
888c2ecf20Sopenharmony_ci	buf[count] = '\0';
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	if (sscanf(buf, "%u", &mode) != 1)
918c2ecf20Sopenharmony_ci		return -EINVAL;
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	if (mode > 255)
948c2ecf20Sopenharmony_ci		return -EBADRQC;
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	pm_runtime_get_sync(ci->dev);
978c2ecf20Sopenharmony_ci	spin_lock_irqsave(&ci->lock, flags);
988c2ecf20Sopenharmony_ci	ret = hw_port_test_set(ci, mode);
998c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&ci->lock, flags);
1008c2ecf20Sopenharmony_ci	pm_runtime_put_sync(ci->dev);
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	return ret ? ret : count;
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_cistatic int ci_port_test_open(struct inode *inode, struct file *file)
1068c2ecf20Sopenharmony_ci{
1078c2ecf20Sopenharmony_ci	return single_open(file, ci_port_test_show, inode->i_private);
1088c2ecf20Sopenharmony_ci}
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_cistatic const struct file_operations ci_port_test_fops = {
1118c2ecf20Sopenharmony_ci	.open		= ci_port_test_open,
1128c2ecf20Sopenharmony_ci	.write		= ci_port_test_write,
1138c2ecf20Sopenharmony_ci	.read		= seq_read,
1148c2ecf20Sopenharmony_ci	.llseek		= seq_lseek,
1158c2ecf20Sopenharmony_ci	.release	= single_release,
1168c2ecf20Sopenharmony_ci};
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci/*
1198c2ecf20Sopenharmony_ci * ci_qheads_show: DMA contents of all queue heads
1208c2ecf20Sopenharmony_ci */
1218c2ecf20Sopenharmony_cistatic int ci_qheads_show(struct seq_file *s, void *data)
1228c2ecf20Sopenharmony_ci{
1238c2ecf20Sopenharmony_ci	struct ci_hdrc *ci = s->private;
1248c2ecf20Sopenharmony_ci	unsigned long flags;
1258c2ecf20Sopenharmony_ci	unsigned i, j;
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	if (ci->role != CI_ROLE_GADGET) {
1288c2ecf20Sopenharmony_ci		seq_printf(s, "not in gadget mode\n");
1298c2ecf20Sopenharmony_ci		return 0;
1308c2ecf20Sopenharmony_ci	}
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	spin_lock_irqsave(&ci->lock, flags);
1338c2ecf20Sopenharmony_ci	for (i = 0; i < ci->hw_ep_max/2; i++) {
1348c2ecf20Sopenharmony_ci		struct ci_hw_ep *hweprx = &ci->ci_hw_ep[i];
1358c2ecf20Sopenharmony_ci		struct ci_hw_ep *hweptx =
1368c2ecf20Sopenharmony_ci			&ci->ci_hw_ep[i + ci->hw_ep_max/2];
1378c2ecf20Sopenharmony_ci		seq_printf(s, "EP=%02i: RX=%08X TX=%08X\n",
1388c2ecf20Sopenharmony_ci			   i, (u32)hweprx->qh.dma, (u32)hweptx->qh.dma);
1398c2ecf20Sopenharmony_ci		for (j = 0; j < (sizeof(struct ci_hw_qh)/sizeof(u32)); j++)
1408c2ecf20Sopenharmony_ci			seq_printf(s, " %04X:    %08X    %08X\n", j,
1418c2ecf20Sopenharmony_ci				   *((u32 *)hweprx->qh.ptr + j),
1428c2ecf20Sopenharmony_ci				   *((u32 *)hweptx->qh.ptr + j));
1438c2ecf20Sopenharmony_ci	}
1448c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&ci->lock, flags);
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	return 0;
1478c2ecf20Sopenharmony_ci}
1488c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(ci_qheads);
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci/*
1518c2ecf20Sopenharmony_ci * ci_requests_show: DMA contents of all requests currently queued (all endpts)
1528c2ecf20Sopenharmony_ci */
1538c2ecf20Sopenharmony_cistatic int ci_requests_show(struct seq_file *s, void *data)
1548c2ecf20Sopenharmony_ci{
1558c2ecf20Sopenharmony_ci	struct ci_hdrc *ci = s->private;
1568c2ecf20Sopenharmony_ci	unsigned long flags;
1578c2ecf20Sopenharmony_ci	struct ci_hw_req *req = NULL;
1588c2ecf20Sopenharmony_ci	struct td_node *node, *tmpnode;
1598c2ecf20Sopenharmony_ci	unsigned i, j, qsize = sizeof(struct ci_hw_td)/sizeof(u32);
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	if (ci->role != CI_ROLE_GADGET) {
1628c2ecf20Sopenharmony_ci		seq_printf(s, "not in gadget mode\n");
1638c2ecf20Sopenharmony_ci		return 0;
1648c2ecf20Sopenharmony_ci	}
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	spin_lock_irqsave(&ci->lock, flags);
1678c2ecf20Sopenharmony_ci	for (i = 0; i < ci->hw_ep_max; i++)
1688c2ecf20Sopenharmony_ci		list_for_each_entry(req, &ci->ci_hw_ep[i].qh.queue, queue) {
1698c2ecf20Sopenharmony_ci			list_for_each_entry_safe(node, tmpnode, &req->tds, td) {
1708c2ecf20Sopenharmony_ci				seq_printf(s, "EP=%02i: TD=%08X %s\n",
1718c2ecf20Sopenharmony_ci					   i % (ci->hw_ep_max / 2),
1728c2ecf20Sopenharmony_ci					   (u32)node->dma,
1738c2ecf20Sopenharmony_ci					   ((i < ci->hw_ep_max/2) ?
1748c2ecf20Sopenharmony_ci					   "RX" : "TX"));
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci				for (j = 0; j < qsize; j++)
1778c2ecf20Sopenharmony_ci					seq_printf(s, " %04X:    %08X\n", j,
1788c2ecf20Sopenharmony_ci						   *((u32 *)node->ptr + j));
1798c2ecf20Sopenharmony_ci			}
1808c2ecf20Sopenharmony_ci		}
1818c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&ci->lock, flags);
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	return 0;
1848c2ecf20Sopenharmony_ci}
1858c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(ci_requests);
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_cistatic int ci_otg_show(struct seq_file *s, void *unused)
1888c2ecf20Sopenharmony_ci{
1898c2ecf20Sopenharmony_ci	struct ci_hdrc *ci = s->private;
1908c2ecf20Sopenharmony_ci	struct otg_fsm *fsm;
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	if (!ci || !ci_otg_is_fsm_mode(ci))
1938c2ecf20Sopenharmony_ci		return 0;
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	fsm = &ci->fsm;
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	/* ------ State ----- */
1988c2ecf20Sopenharmony_ci	seq_printf(s, "OTG state: %s\n\n",
1998c2ecf20Sopenharmony_ci			usb_otg_state_string(ci->otg.state));
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	/* ------ State Machine Variables ----- */
2028c2ecf20Sopenharmony_ci	seq_printf(s, "a_bus_drop: %d\n", fsm->a_bus_drop);
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	seq_printf(s, "a_bus_req: %d\n", fsm->a_bus_req);
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	seq_printf(s, "a_srp_det: %d\n", fsm->a_srp_det);
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	seq_printf(s, "a_vbus_vld: %d\n", fsm->a_vbus_vld);
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	seq_printf(s, "b_conn: %d\n", fsm->b_conn);
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	seq_printf(s, "adp_change: %d\n", fsm->adp_change);
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci	seq_printf(s, "power_up: %d\n", fsm->power_up);
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	seq_printf(s, "a_bus_resume: %d\n", fsm->a_bus_resume);
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	seq_printf(s, "a_bus_suspend: %d\n", fsm->a_bus_suspend);
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	seq_printf(s, "a_conn: %d\n", fsm->a_conn);
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	seq_printf(s, "b_bus_req: %d\n", fsm->b_bus_req);
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	seq_printf(s, "b_bus_suspend: %d\n", fsm->b_bus_suspend);
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	seq_printf(s, "b_se0_srp: %d\n", fsm->b_se0_srp);
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	seq_printf(s, "b_ssend_srp: %d\n", fsm->b_ssend_srp);
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	seq_printf(s, "b_sess_vld: %d\n", fsm->b_sess_vld);
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	seq_printf(s, "b_srp_done: %d\n", fsm->b_srp_done);
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	seq_printf(s, "drv_vbus: %d\n", fsm->drv_vbus);
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	seq_printf(s, "loc_conn: %d\n", fsm->loc_conn);
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	seq_printf(s, "loc_sof: %d\n", fsm->loc_sof);
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	seq_printf(s, "adp_prb: %d\n", fsm->adp_prb);
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	seq_printf(s, "id: %d\n", fsm->id);
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	seq_printf(s, "protocol: %d\n", fsm->protocol);
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci	return 0;
2478c2ecf20Sopenharmony_ci}
2488c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(ci_otg);
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_cistatic int ci_role_show(struct seq_file *s, void *data)
2518c2ecf20Sopenharmony_ci{
2528c2ecf20Sopenharmony_ci	struct ci_hdrc *ci = s->private;
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	if (ci->role != CI_ROLE_END)
2558c2ecf20Sopenharmony_ci		seq_printf(s, "%s\n", ci_role(ci)->name);
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	return 0;
2588c2ecf20Sopenharmony_ci}
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_cistatic ssize_t ci_role_write(struct file *file, const char __user *ubuf,
2618c2ecf20Sopenharmony_ci			     size_t count, loff_t *ppos)
2628c2ecf20Sopenharmony_ci{
2638c2ecf20Sopenharmony_ci	struct seq_file *s = file->private_data;
2648c2ecf20Sopenharmony_ci	struct ci_hdrc *ci = s->private;
2658c2ecf20Sopenharmony_ci	enum ci_role role;
2668c2ecf20Sopenharmony_ci	char buf[8];
2678c2ecf20Sopenharmony_ci	int ret;
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
2708c2ecf20Sopenharmony_ci		return -EFAULT;
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci	for (role = CI_ROLE_HOST; role < CI_ROLE_END; role++)
2738c2ecf20Sopenharmony_ci		if (ci->roles[role] &&
2748c2ecf20Sopenharmony_ci		    !strncmp(buf, ci->roles[role]->name,
2758c2ecf20Sopenharmony_ci			     strlen(ci->roles[role]->name)))
2768c2ecf20Sopenharmony_ci			break;
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	if (role == CI_ROLE_END || role == ci->role)
2798c2ecf20Sopenharmony_ci		return -EINVAL;
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci	pm_runtime_get_sync(ci->dev);
2828c2ecf20Sopenharmony_ci	disable_irq(ci->irq);
2838c2ecf20Sopenharmony_ci	ci_role_stop(ci);
2848c2ecf20Sopenharmony_ci	ret = ci_role_start(ci, role);
2858c2ecf20Sopenharmony_ci	enable_irq(ci->irq);
2868c2ecf20Sopenharmony_ci	pm_runtime_put_sync(ci->dev);
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	return ret ? ret : count;
2898c2ecf20Sopenharmony_ci}
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_cistatic int ci_role_open(struct inode *inode, struct file *file)
2928c2ecf20Sopenharmony_ci{
2938c2ecf20Sopenharmony_ci	return single_open(file, ci_role_show, inode->i_private);
2948c2ecf20Sopenharmony_ci}
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_cistatic const struct file_operations ci_role_fops = {
2978c2ecf20Sopenharmony_ci	.open		= ci_role_open,
2988c2ecf20Sopenharmony_ci	.write		= ci_role_write,
2998c2ecf20Sopenharmony_ci	.read		= seq_read,
3008c2ecf20Sopenharmony_ci	.llseek		= seq_lseek,
3018c2ecf20Sopenharmony_ci	.release	= single_release,
3028c2ecf20Sopenharmony_ci};
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_cistatic int ci_registers_show(struct seq_file *s, void *unused)
3058c2ecf20Sopenharmony_ci{
3068c2ecf20Sopenharmony_ci	struct ci_hdrc *ci = s->private;
3078c2ecf20Sopenharmony_ci	u32 tmp_reg;
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci	if (!ci || ci->in_lpm)
3108c2ecf20Sopenharmony_ci		return -EPERM;
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	/* ------ Registers ----- */
3138c2ecf20Sopenharmony_ci	tmp_reg = hw_read_intr_enable(ci);
3148c2ecf20Sopenharmony_ci	seq_printf(s, "USBINTR reg: %08x\n", tmp_reg);
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	tmp_reg = hw_read_intr_status(ci);
3178c2ecf20Sopenharmony_ci	seq_printf(s, "USBSTS reg: %08x\n", tmp_reg);
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	tmp_reg = hw_read(ci, OP_USBMODE, ~0);
3208c2ecf20Sopenharmony_ci	seq_printf(s, "USBMODE reg: %08x\n", tmp_reg);
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	tmp_reg = hw_read(ci, OP_USBCMD, ~0);
3238c2ecf20Sopenharmony_ci	seq_printf(s, "USBCMD reg: %08x\n", tmp_reg);
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	tmp_reg = hw_read(ci, OP_PORTSC, ~0);
3268c2ecf20Sopenharmony_ci	seq_printf(s, "PORTSC reg: %08x\n", tmp_reg);
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci	if (ci->is_otg) {
3298c2ecf20Sopenharmony_ci		tmp_reg = hw_read_otgsc(ci, ~0);
3308c2ecf20Sopenharmony_ci		seq_printf(s, "OTGSC reg: %08x\n", tmp_reg);
3318c2ecf20Sopenharmony_ci	}
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	return 0;
3348c2ecf20Sopenharmony_ci}
3358c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(ci_registers);
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci/**
3388c2ecf20Sopenharmony_ci * dbg_create_files: initializes the attribute interface
3398c2ecf20Sopenharmony_ci * @ci: device
3408c2ecf20Sopenharmony_ci *
3418c2ecf20Sopenharmony_ci * This function returns an error code
3428c2ecf20Sopenharmony_ci */
3438c2ecf20Sopenharmony_civoid dbg_create_files(struct ci_hdrc *ci)
3448c2ecf20Sopenharmony_ci{
3458c2ecf20Sopenharmony_ci	ci->debugfs = debugfs_create_dir(dev_name(ci->dev), usb_debug_root);
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	debugfs_create_file("device", S_IRUGO, ci->debugfs, ci,
3488c2ecf20Sopenharmony_ci			    &ci_device_fops);
3498c2ecf20Sopenharmony_ci	debugfs_create_file("port_test", S_IRUGO | S_IWUSR, ci->debugfs, ci,
3508c2ecf20Sopenharmony_ci			    &ci_port_test_fops);
3518c2ecf20Sopenharmony_ci	debugfs_create_file("qheads", S_IRUGO, ci->debugfs, ci,
3528c2ecf20Sopenharmony_ci			    &ci_qheads_fops);
3538c2ecf20Sopenharmony_ci	debugfs_create_file("requests", S_IRUGO, ci->debugfs, ci,
3548c2ecf20Sopenharmony_ci			    &ci_requests_fops);
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci	if (ci_otg_is_fsm_mode(ci)) {
3578c2ecf20Sopenharmony_ci		debugfs_create_file("otg", S_IRUGO, ci->debugfs, ci,
3588c2ecf20Sopenharmony_ci				    &ci_otg_fops);
3598c2ecf20Sopenharmony_ci	}
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	debugfs_create_file("role", S_IRUGO | S_IWUSR, ci->debugfs, ci,
3628c2ecf20Sopenharmony_ci			    &ci_role_fops);
3638c2ecf20Sopenharmony_ci	debugfs_create_file("registers", S_IRUGO, ci->debugfs, ci,
3648c2ecf20Sopenharmony_ci			    &ci_registers_fops);
3658c2ecf20Sopenharmony_ci}
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci/**
3688c2ecf20Sopenharmony_ci * dbg_remove_files: destroys the attribute interface
3698c2ecf20Sopenharmony_ci * @ci: device
3708c2ecf20Sopenharmony_ci */
3718c2ecf20Sopenharmony_civoid dbg_remove_files(struct ci_hdrc *ci)
3728c2ecf20Sopenharmony_ci{
3738c2ecf20Sopenharmony_ci	debugfs_remove_recursive(ci->debugfs);
3748c2ecf20Sopenharmony_ci}
375