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