18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * MUSB OTG driver debugfs support
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright 2010 Nokia Corporation
68c2ecf20Sopenharmony_ci * Contact: Felipe Balbi <felipe.balbi@nokia.com>
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/module.h>
108c2ecf20Sopenharmony_ci#include <linux/kernel.h>
118c2ecf20Sopenharmony_ci#include <linux/init.h>
128c2ecf20Sopenharmony_ci#include <linux/debugfs.h>
138c2ecf20Sopenharmony_ci#include <linux/seq_file.h>
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#include "musb_core.h"
188c2ecf20Sopenharmony_ci#include "musb_debug.h"
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_cistruct musb_register_map {
218c2ecf20Sopenharmony_ci	char			*name;
228c2ecf20Sopenharmony_ci	unsigned		offset;
238c2ecf20Sopenharmony_ci	unsigned		size;
248c2ecf20Sopenharmony_ci};
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_cistatic const struct musb_register_map musb_regmap[] = {
278c2ecf20Sopenharmony_ci	{ "FAddr",	MUSB_FADDR,	8 },
288c2ecf20Sopenharmony_ci	{ "Power",	MUSB_POWER,	8 },
298c2ecf20Sopenharmony_ci	{ "Frame",	MUSB_FRAME,	16 },
308c2ecf20Sopenharmony_ci	{ "Index",	MUSB_INDEX,	8 },
318c2ecf20Sopenharmony_ci	{ "Testmode",	MUSB_TESTMODE,	8 },
328c2ecf20Sopenharmony_ci	{ "TxMaxPp",	MUSB_TXMAXP,	16 },
338c2ecf20Sopenharmony_ci	{ "TxCSRp",	MUSB_TXCSR,	16 },
348c2ecf20Sopenharmony_ci	{ "RxMaxPp",	MUSB_RXMAXP,	16 },
358c2ecf20Sopenharmony_ci	{ "RxCSR",	MUSB_RXCSR,	16 },
368c2ecf20Sopenharmony_ci	{ "RxCount",	MUSB_RXCOUNT,	16 },
378c2ecf20Sopenharmony_ci	{ "IntrRxE",	MUSB_INTRRXE,	16 },
388c2ecf20Sopenharmony_ci	{ "IntrTxE",	MUSB_INTRTXE,	16 },
398c2ecf20Sopenharmony_ci	{ "IntrUsbE",	MUSB_INTRUSBE,	8 },
408c2ecf20Sopenharmony_ci	{ "DevCtl",	MUSB_DEVCTL,	8 },
418c2ecf20Sopenharmony_ci	{ "VControl",	0x68,		32 },
428c2ecf20Sopenharmony_ci	{ "HWVers",	MUSB_HWVERS,	16 },
438c2ecf20Sopenharmony_ci	{ "LinkInfo",	MUSB_LINKINFO,	8 },
448c2ecf20Sopenharmony_ci	{ "VPLen",	MUSB_VPLEN,	8 },
458c2ecf20Sopenharmony_ci	{ "HS_EOF1",	MUSB_HS_EOF1,	8 },
468c2ecf20Sopenharmony_ci	{ "FS_EOF1",	MUSB_FS_EOF1,	8 },
478c2ecf20Sopenharmony_ci	{ "LS_EOF1",	MUSB_LS_EOF1,	8 },
488c2ecf20Sopenharmony_ci	{ "SOFT_RST",	0x7F,		8 },
498c2ecf20Sopenharmony_ci	{ "DMA_CNTLch0",	0x204,	16 },
508c2ecf20Sopenharmony_ci	{ "DMA_ADDRch0",	0x208,	32 },
518c2ecf20Sopenharmony_ci	{ "DMA_COUNTch0",	0x20C,	32 },
528c2ecf20Sopenharmony_ci	{ "DMA_CNTLch1",	0x214,	16 },
538c2ecf20Sopenharmony_ci	{ "DMA_ADDRch1",	0x218,	32 },
548c2ecf20Sopenharmony_ci	{ "DMA_COUNTch1",	0x21C,	32 },
558c2ecf20Sopenharmony_ci	{ "DMA_CNTLch2",	0x224,	16 },
568c2ecf20Sopenharmony_ci	{ "DMA_ADDRch2",	0x228,	32 },
578c2ecf20Sopenharmony_ci	{ "DMA_COUNTch2",	0x22C,	32 },
588c2ecf20Sopenharmony_ci	{ "DMA_CNTLch3",	0x234,	16 },
598c2ecf20Sopenharmony_ci	{ "DMA_ADDRch3",	0x238,	32 },
608c2ecf20Sopenharmony_ci	{ "DMA_COUNTch3",	0x23C,	32 },
618c2ecf20Sopenharmony_ci	{ "DMA_CNTLch4",	0x244,	16 },
628c2ecf20Sopenharmony_ci	{ "DMA_ADDRch4",	0x248,	32 },
638c2ecf20Sopenharmony_ci	{ "DMA_COUNTch4",	0x24C,	32 },
648c2ecf20Sopenharmony_ci	{ "DMA_CNTLch5",	0x254,	16 },
658c2ecf20Sopenharmony_ci	{ "DMA_ADDRch5",	0x258,	32 },
668c2ecf20Sopenharmony_ci	{ "DMA_COUNTch5",	0x25C,	32 },
678c2ecf20Sopenharmony_ci	{ "DMA_CNTLch6",	0x264,	16 },
688c2ecf20Sopenharmony_ci	{ "DMA_ADDRch6",	0x268,	32 },
698c2ecf20Sopenharmony_ci	{ "DMA_COUNTch6",	0x26C,	32 },
708c2ecf20Sopenharmony_ci	{ "DMA_CNTLch7",	0x274,	16 },
718c2ecf20Sopenharmony_ci	{ "DMA_ADDRch7",	0x278,	32 },
728c2ecf20Sopenharmony_ci	{ "DMA_COUNTch7",	0x27C,	32 },
738c2ecf20Sopenharmony_ci	{ "ConfigData",	MUSB_CONFIGDATA,8 },
748c2ecf20Sopenharmony_ci	{ "BabbleCtl",	MUSB_BABBLE_CTL,8 },
758c2ecf20Sopenharmony_ci	{ "TxFIFOsz",	MUSB_TXFIFOSZ,	8 },
768c2ecf20Sopenharmony_ci	{ "RxFIFOsz",	MUSB_RXFIFOSZ,	8 },
778c2ecf20Sopenharmony_ci	{ "TxFIFOadd",	MUSB_TXFIFOADD,	16 },
788c2ecf20Sopenharmony_ci	{ "RxFIFOadd",	MUSB_RXFIFOADD,	16 },
798c2ecf20Sopenharmony_ci	{ "EPInfo",	MUSB_EPINFO,	8 },
808c2ecf20Sopenharmony_ci	{ "RAMInfo",	MUSB_RAMINFO,	8 },
818c2ecf20Sopenharmony_ci	{  }	/* Terminating Entry */
828c2ecf20Sopenharmony_ci};
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_cistatic int musb_regdump_show(struct seq_file *s, void *unused)
858c2ecf20Sopenharmony_ci{
868c2ecf20Sopenharmony_ci	struct musb		*musb = s->private;
878c2ecf20Sopenharmony_ci	unsigned		i;
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	seq_printf(s, "MUSB (M)HDRC Register Dump\n");
908c2ecf20Sopenharmony_ci	pm_runtime_get_sync(musb->controller);
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(musb_regmap); i++) {
938c2ecf20Sopenharmony_ci		switch (musb_regmap[i].size) {
948c2ecf20Sopenharmony_ci		case 8:
958c2ecf20Sopenharmony_ci			seq_printf(s, "%-12s: %02x\n", musb_regmap[i].name,
968c2ecf20Sopenharmony_ci					musb_readb(musb->mregs, musb_regmap[i].offset));
978c2ecf20Sopenharmony_ci			break;
988c2ecf20Sopenharmony_ci		case 16:
998c2ecf20Sopenharmony_ci			seq_printf(s, "%-12s: %04x\n", musb_regmap[i].name,
1008c2ecf20Sopenharmony_ci					musb_readw(musb->mregs, musb_regmap[i].offset));
1018c2ecf20Sopenharmony_ci			break;
1028c2ecf20Sopenharmony_ci		case 32:
1038c2ecf20Sopenharmony_ci			seq_printf(s, "%-12s: %08x\n", musb_regmap[i].name,
1048c2ecf20Sopenharmony_ci					musb_readl(musb->mregs, musb_regmap[i].offset));
1058c2ecf20Sopenharmony_ci			break;
1068c2ecf20Sopenharmony_ci		}
1078c2ecf20Sopenharmony_ci	}
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	pm_runtime_mark_last_busy(musb->controller);
1108c2ecf20Sopenharmony_ci	pm_runtime_put_autosuspend(musb->controller);
1118c2ecf20Sopenharmony_ci	return 0;
1128c2ecf20Sopenharmony_ci}
1138c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(musb_regdump);
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_cistatic int musb_test_mode_show(struct seq_file *s, void *unused)
1168c2ecf20Sopenharmony_ci{
1178c2ecf20Sopenharmony_ci	struct musb		*musb = s->private;
1188c2ecf20Sopenharmony_ci	unsigned		test;
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	pm_runtime_get_sync(musb->controller);
1218c2ecf20Sopenharmony_ci	test = musb_readb(musb->mregs, MUSB_TESTMODE);
1228c2ecf20Sopenharmony_ci	pm_runtime_mark_last_busy(musb->controller);
1238c2ecf20Sopenharmony_ci	pm_runtime_put_autosuspend(musb->controller);
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	if (test == (MUSB_TEST_FORCE_HOST | MUSB_TEST_FORCE_FS))
1268c2ecf20Sopenharmony_ci		seq_printf(s, "force host full-speed\n");
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	else if (test == (MUSB_TEST_FORCE_HOST | MUSB_TEST_FORCE_HS))
1298c2ecf20Sopenharmony_ci		seq_printf(s, "force host high-speed\n");
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	else if (test == MUSB_TEST_FORCE_HOST)
1328c2ecf20Sopenharmony_ci		seq_printf(s, "force host\n");
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	else if (test == MUSB_TEST_FIFO_ACCESS)
1358c2ecf20Sopenharmony_ci		seq_printf(s, "fifo access\n");
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	else if (test == MUSB_TEST_FORCE_FS)
1388c2ecf20Sopenharmony_ci		seq_printf(s, "force full-speed\n");
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	else if (test == MUSB_TEST_FORCE_HS)
1418c2ecf20Sopenharmony_ci		seq_printf(s, "force high-speed\n");
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	else if (test == MUSB_TEST_PACKET)
1448c2ecf20Sopenharmony_ci		seq_printf(s, "test packet\n");
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	else if (test == MUSB_TEST_K)
1478c2ecf20Sopenharmony_ci		seq_printf(s, "test K\n");
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	else if (test == MUSB_TEST_J)
1508c2ecf20Sopenharmony_ci		seq_printf(s, "test J\n");
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	else if (test == MUSB_TEST_SE0_NAK)
1538c2ecf20Sopenharmony_ci		seq_printf(s, "test SE0 NAK\n");
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	return 0;
1568c2ecf20Sopenharmony_ci}
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_cistatic int musb_test_mode_open(struct inode *inode, struct file *file)
1598c2ecf20Sopenharmony_ci{
1608c2ecf20Sopenharmony_ci	return single_open(file, musb_test_mode_show, inode->i_private);
1618c2ecf20Sopenharmony_ci}
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_cistatic ssize_t musb_test_mode_write(struct file *file,
1648c2ecf20Sopenharmony_ci		const char __user *ubuf, size_t count, loff_t *ppos)
1658c2ecf20Sopenharmony_ci{
1668c2ecf20Sopenharmony_ci	struct seq_file		*s = file->private_data;
1678c2ecf20Sopenharmony_ci	struct musb		*musb = s->private;
1688c2ecf20Sopenharmony_ci	u8			test;
1698c2ecf20Sopenharmony_ci	char			buf[24];
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	memset(buf, 0x00, sizeof(buf));
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
1748c2ecf20Sopenharmony_ci		return -EFAULT;
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	pm_runtime_get_sync(musb->controller);
1778c2ecf20Sopenharmony_ci	test = musb_readb(musb->mregs, MUSB_TESTMODE);
1788c2ecf20Sopenharmony_ci	if (test) {
1798c2ecf20Sopenharmony_ci		dev_err(musb->controller, "Error: test mode is already set. "
1808c2ecf20Sopenharmony_ci			"Please do USB Bus Reset to start a new test.\n");
1818c2ecf20Sopenharmony_ci		goto ret;
1828c2ecf20Sopenharmony_ci	}
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci	if (strstarts(buf, "force host full-speed"))
1858c2ecf20Sopenharmony_ci		test = MUSB_TEST_FORCE_HOST | MUSB_TEST_FORCE_FS;
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	else if (strstarts(buf, "force host high-speed"))
1888c2ecf20Sopenharmony_ci		test = MUSB_TEST_FORCE_HOST | MUSB_TEST_FORCE_HS;
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	else if (strstarts(buf, "force host"))
1918c2ecf20Sopenharmony_ci		test = MUSB_TEST_FORCE_HOST;
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci	else if (strstarts(buf, "fifo access"))
1948c2ecf20Sopenharmony_ci		test = MUSB_TEST_FIFO_ACCESS;
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	else if (strstarts(buf, "force full-speed"))
1978c2ecf20Sopenharmony_ci		test = MUSB_TEST_FORCE_FS;
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	else if (strstarts(buf, "force high-speed"))
2008c2ecf20Sopenharmony_ci		test = MUSB_TEST_FORCE_HS;
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	else if (strstarts(buf, "test packet")) {
2038c2ecf20Sopenharmony_ci		test = MUSB_TEST_PACKET;
2048c2ecf20Sopenharmony_ci		musb_load_testpacket(musb);
2058c2ecf20Sopenharmony_ci	}
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	else if (strstarts(buf, "test K"))
2088c2ecf20Sopenharmony_ci		test = MUSB_TEST_K;
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	else if (strstarts(buf, "test J"))
2118c2ecf20Sopenharmony_ci		test = MUSB_TEST_J;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	else if (strstarts(buf, "test SE0 NAK"))
2148c2ecf20Sopenharmony_ci		test = MUSB_TEST_SE0_NAK;
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	musb_writeb(musb->mregs, MUSB_TESTMODE, test);
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ciret:
2198c2ecf20Sopenharmony_ci	pm_runtime_mark_last_busy(musb->controller);
2208c2ecf20Sopenharmony_ci	pm_runtime_put_autosuspend(musb->controller);
2218c2ecf20Sopenharmony_ci	return count;
2228c2ecf20Sopenharmony_ci}
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_cistatic const struct file_operations musb_test_mode_fops = {
2258c2ecf20Sopenharmony_ci	.open			= musb_test_mode_open,
2268c2ecf20Sopenharmony_ci	.write			= musb_test_mode_write,
2278c2ecf20Sopenharmony_ci	.read			= seq_read,
2288c2ecf20Sopenharmony_ci	.llseek			= seq_lseek,
2298c2ecf20Sopenharmony_ci	.release		= single_release,
2308c2ecf20Sopenharmony_ci};
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_cistatic int musb_softconnect_show(struct seq_file *s, void *unused)
2338c2ecf20Sopenharmony_ci{
2348c2ecf20Sopenharmony_ci	struct musb	*musb = s->private;
2358c2ecf20Sopenharmony_ci	u8		reg;
2368c2ecf20Sopenharmony_ci	int		connect;
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	switch (musb->xceiv->otg->state) {
2398c2ecf20Sopenharmony_ci	case OTG_STATE_A_HOST:
2408c2ecf20Sopenharmony_ci	case OTG_STATE_A_WAIT_BCON:
2418c2ecf20Sopenharmony_ci		pm_runtime_get_sync(musb->controller);
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci		reg = musb_readb(musb->mregs, MUSB_DEVCTL);
2448c2ecf20Sopenharmony_ci		connect = reg & MUSB_DEVCTL_SESSION ? 1 : 0;
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci		pm_runtime_mark_last_busy(musb->controller);
2478c2ecf20Sopenharmony_ci		pm_runtime_put_autosuspend(musb->controller);
2488c2ecf20Sopenharmony_ci		break;
2498c2ecf20Sopenharmony_ci	default:
2508c2ecf20Sopenharmony_ci		connect = -1;
2518c2ecf20Sopenharmony_ci	}
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	seq_printf(s, "%d\n", connect);
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	return 0;
2568c2ecf20Sopenharmony_ci}
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_cistatic int musb_softconnect_open(struct inode *inode, struct file *file)
2598c2ecf20Sopenharmony_ci{
2608c2ecf20Sopenharmony_ci	return single_open(file, musb_softconnect_show, inode->i_private);
2618c2ecf20Sopenharmony_ci}
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_cistatic ssize_t musb_softconnect_write(struct file *file,
2648c2ecf20Sopenharmony_ci		const char __user *ubuf, size_t count, loff_t *ppos)
2658c2ecf20Sopenharmony_ci{
2668c2ecf20Sopenharmony_ci	struct seq_file		*s = file->private_data;
2678c2ecf20Sopenharmony_ci	struct musb		*musb = s->private;
2688c2ecf20Sopenharmony_ci	char			buf[2];
2698c2ecf20Sopenharmony_ci	u8			reg;
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	memset(buf, 0x00, sizeof(buf));
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
2748c2ecf20Sopenharmony_ci		return -EFAULT;
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	pm_runtime_get_sync(musb->controller);
2778c2ecf20Sopenharmony_ci	if (!strncmp(buf, "0", 1)) {
2788c2ecf20Sopenharmony_ci		switch (musb->xceiv->otg->state) {
2798c2ecf20Sopenharmony_ci		case OTG_STATE_A_HOST:
2808c2ecf20Sopenharmony_ci			musb_root_disconnect(musb);
2818c2ecf20Sopenharmony_ci			reg = musb_readb(musb->mregs, MUSB_DEVCTL);
2828c2ecf20Sopenharmony_ci			reg &= ~MUSB_DEVCTL_SESSION;
2838c2ecf20Sopenharmony_ci			musb_writeb(musb->mregs, MUSB_DEVCTL, reg);
2848c2ecf20Sopenharmony_ci			break;
2858c2ecf20Sopenharmony_ci		default:
2868c2ecf20Sopenharmony_ci			break;
2878c2ecf20Sopenharmony_ci		}
2888c2ecf20Sopenharmony_ci	} else if (!strncmp(buf, "1", 1)) {
2898c2ecf20Sopenharmony_ci		switch (musb->xceiv->otg->state) {
2908c2ecf20Sopenharmony_ci		case OTG_STATE_A_WAIT_BCON:
2918c2ecf20Sopenharmony_ci			/*
2928c2ecf20Sopenharmony_ci			 * musb_save_context() called in musb_runtime_suspend()
2938c2ecf20Sopenharmony_ci			 * might cache devctl with SESSION bit cleared during
2948c2ecf20Sopenharmony_ci			 * soft-disconnect, so specifically set SESSION bit
2958c2ecf20Sopenharmony_ci			 * here to preserve it for musb_runtime_resume().
2968c2ecf20Sopenharmony_ci			 */
2978c2ecf20Sopenharmony_ci			musb->context.devctl |= MUSB_DEVCTL_SESSION;
2988c2ecf20Sopenharmony_ci			reg = musb_readb(musb->mregs, MUSB_DEVCTL);
2998c2ecf20Sopenharmony_ci			reg |= MUSB_DEVCTL_SESSION;
3008c2ecf20Sopenharmony_ci			musb_writeb(musb->mregs, MUSB_DEVCTL, reg);
3018c2ecf20Sopenharmony_ci			break;
3028c2ecf20Sopenharmony_ci		default:
3038c2ecf20Sopenharmony_ci			break;
3048c2ecf20Sopenharmony_ci		}
3058c2ecf20Sopenharmony_ci	}
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	pm_runtime_mark_last_busy(musb->controller);
3088c2ecf20Sopenharmony_ci	pm_runtime_put_autosuspend(musb->controller);
3098c2ecf20Sopenharmony_ci	return count;
3108c2ecf20Sopenharmony_ci}
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci/*
3138c2ecf20Sopenharmony_ci * In host mode, connect/disconnect the bus without physically
3148c2ecf20Sopenharmony_ci * remove the devices.
3158c2ecf20Sopenharmony_ci */
3168c2ecf20Sopenharmony_cistatic const struct file_operations musb_softconnect_fops = {
3178c2ecf20Sopenharmony_ci	.open			= musb_softconnect_open,
3188c2ecf20Sopenharmony_ci	.write			= musb_softconnect_write,
3198c2ecf20Sopenharmony_ci	.read			= seq_read,
3208c2ecf20Sopenharmony_ci	.llseek			= seq_lseek,
3218c2ecf20Sopenharmony_ci	.release		= single_release,
3228c2ecf20Sopenharmony_ci};
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_civoid musb_init_debugfs(struct musb *musb)
3258c2ecf20Sopenharmony_ci{
3268c2ecf20Sopenharmony_ci	struct dentry *root;
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci	root = debugfs_create_dir(dev_name(musb->controller), usb_debug_root);
3298c2ecf20Sopenharmony_ci	musb->debugfs_root = root;
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci	debugfs_create_file("regdump", S_IRUGO, root, musb, &musb_regdump_fops);
3328c2ecf20Sopenharmony_ci	debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root, musb,
3338c2ecf20Sopenharmony_ci			    &musb_test_mode_fops);
3348c2ecf20Sopenharmony_ci	debugfs_create_file("softconnect", S_IRUGO | S_IWUSR, root, musb,
3358c2ecf20Sopenharmony_ci			    &musb_softconnect_fops);
3368c2ecf20Sopenharmony_ci}
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_civoid /* __init_or_exit */ musb_exit_debugfs(struct musb *musb)
3398c2ecf20Sopenharmony_ci{
3408c2ecf20Sopenharmony_ci	debugfs_remove_recursive(musb->debugfs_root);
3418c2ecf20Sopenharmony_ci}
342