18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * mtu3_debugfs.c - debugfs interface 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2019 MediaTek Inc. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Author: Chunfeng Yun <chunfeng.yun@mediatek.com> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include "mtu3.h" 138c2ecf20Sopenharmony_ci#include "mtu3_dr.h" 148c2ecf20Sopenharmony_ci#include "mtu3_debug.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#define dump_register(nm) \ 178c2ecf20Sopenharmony_ci{ \ 188c2ecf20Sopenharmony_ci .name = __stringify(nm), \ 198c2ecf20Sopenharmony_ci .offset = U3D_ ##nm, \ 208c2ecf20Sopenharmony_ci} 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#define dump_prb_reg(nm, os) \ 238c2ecf20Sopenharmony_ci{ \ 248c2ecf20Sopenharmony_ci .name = nm, \ 258c2ecf20Sopenharmony_ci .offset = os, \ 268c2ecf20Sopenharmony_ci} 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic const struct debugfs_reg32 mtu3_ippc_regs[] = { 298c2ecf20Sopenharmony_ci dump_register(SSUSB_IP_PW_CTRL0), 308c2ecf20Sopenharmony_ci dump_register(SSUSB_IP_PW_CTRL1), 318c2ecf20Sopenharmony_ci dump_register(SSUSB_IP_PW_CTRL2), 328c2ecf20Sopenharmony_ci dump_register(SSUSB_IP_PW_CTRL3), 338c2ecf20Sopenharmony_ci dump_register(SSUSB_OTG_STS), 348c2ecf20Sopenharmony_ci dump_register(SSUSB_IP_XHCI_CAP), 358c2ecf20Sopenharmony_ci dump_register(SSUSB_IP_DEV_CAP), 368c2ecf20Sopenharmony_ci dump_register(SSUSB_U3_CTRL_0P), 378c2ecf20Sopenharmony_ci dump_register(SSUSB_U2_CTRL_0P), 388c2ecf20Sopenharmony_ci dump_register(SSUSB_HW_ID), 398c2ecf20Sopenharmony_ci dump_register(SSUSB_HW_SUB_ID), 408c2ecf20Sopenharmony_ci dump_register(SSUSB_IP_SPARE0), 418c2ecf20Sopenharmony_ci}; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_cistatic const struct debugfs_reg32 mtu3_dev_regs[] = { 448c2ecf20Sopenharmony_ci dump_register(LV1ISR), 458c2ecf20Sopenharmony_ci dump_register(LV1IER), 468c2ecf20Sopenharmony_ci dump_register(EPISR), 478c2ecf20Sopenharmony_ci dump_register(EPIER), 488c2ecf20Sopenharmony_ci dump_register(EP0CSR), 498c2ecf20Sopenharmony_ci dump_register(RXCOUNT0), 508c2ecf20Sopenharmony_ci dump_register(QISAR0), 518c2ecf20Sopenharmony_ci dump_register(QIER0), 528c2ecf20Sopenharmony_ci dump_register(QISAR1), 538c2ecf20Sopenharmony_ci dump_register(QIER1), 548c2ecf20Sopenharmony_ci dump_register(CAP_EPNTXFFSZ), 558c2ecf20Sopenharmony_ci dump_register(CAP_EPNRXFFSZ), 568c2ecf20Sopenharmony_ci dump_register(CAP_EPINFO), 578c2ecf20Sopenharmony_ci dump_register(MISC_CTRL), 588c2ecf20Sopenharmony_ci}; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cistatic const struct debugfs_reg32 mtu3_csr_regs[] = { 618c2ecf20Sopenharmony_ci dump_register(DEVICE_CONF), 628c2ecf20Sopenharmony_ci dump_register(DEV_LINK_INTR_ENABLE), 638c2ecf20Sopenharmony_ci dump_register(DEV_LINK_INTR), 648c2ecf20Sopenharmony_ci dump_register(LTSSM_CTRL), 658c2ecf20Sopenharmony_ci dump_register(USB3_CONFIG), 668c2ecf20Sopenharmony_ci dump_register(LINK_STATE_MACHINE), 678c2ecf20Sopenharmony_ci dump_register(LTSSM_INTR_ENABLE), 688c2ecf20Sopenharmony_ci dump_register(LTSSM_INTR), 698c2ecf20Sopenharmony_ci dump_register(U3U2_SWITCH_CTRL), 708c2ecf20Sopenharmony_ci dump_register(POWER_MANAGEMENT), 718c2ecf20Sopenharmony_ci dump_register(DEVICE_CONTROL), 728c2ecf20Sopenharmony_ci dump_register(COMMON_USB_INTR_ENABLE), 738c2ecf20Sopenharmony_ci dump_register(COMMON_USB_INTR), 748c2ecf20Sopenharmony_ci dump_register(USB20_MISC_CONTROL), 758c2ecf20Sopenharmony_ci dump_register(USB20_OPSTATE), 768c2ecf20Sopenharmony_ci}; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistatic int mtu3_link_state_show(struct seq_file *sf, void *unused) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci struct mtu3 *mtu = sf->private; 818c2ecf20Sopenharmony_ci void __iomem *mbase = mtu->mac_base; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci seq_printf(sf, "opstate: %#x, ltssm: %#x\n", 848c2ecf20Sopenharmony_ci mtu3_readl(mbase, U3D_USB20_OPSTATE), 858c2ecf20Sopenharmony_ci LTSSM_STATE(mtu3_readl(mbase, U3D_LINK_STATE_MACHINE))); 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci return 0; 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic int mtu3_ep_used_show(struct seq_file *sf, void *unused) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci struct mtu3 *mtu = sf->private; 938c2ecf20Sopenharmony_ci struct mtu3_ep *mep; 948c2ecf20Sopenharmony_ci unsigned long flags; 958c2ecf20Sopenharmony_ci int used = 0; 968c2ecf20Sopenharmony_ci int i; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci spin_lock_irqsave(&mtu->lock, flags); 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci for (i = 0; i < mtu->num_eps; i++) { 1018c2ecf20Sopenharmony_ci mep = mtu->in_eps + i; 1028c2ecf20Sopenharmony_ci if (mep->flags & MTU3_EP_ENABLED) { 1038c2ecf20Sopenharmony_ci seq_printf(sf, "%s - type: %d\n", mep->name, mep->type); 1048c2ecf20Sopenharmony_ci used++; 1058c2ecf20Sopenharmony_ci } 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci mep = mtu->out_eps + i; 1088c2ecf20Sopenharmony_ci if (mep->flags & MTU3_EP_ENABLED) { 1098c2ecf20Sopenharmony_ci seq_printf(sf, "%s - type: %d\n", mep->name, mep->type); 1108c2ecf20Sopenharmony_ci used++; 1118c2ecf20Sopenharmony_ci } 1128c2ecf20Sopenharmony_ci } 1138c2ecf20Sopenharmony_ci seq_printf(sf, "total used: %d eps\n", used); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&mtu->lock, flags); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci return 0; 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(mtu3_link_state); 1218c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(mtu3_ep_used); 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistatic void mtu3_debugfs_regset(struct mtu3 *mtu, void __iomem *base, 1248c2ecf20Sopenharmony_ci const struct debugfs_reg32 *regs, size_t nregs, 1258c2ecf20Sopenharmony_ci const char *name, struct dentry *parent) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci struct debugfs_regset32 *regset; 1288c2ecf20Sopenharmony_ci struct mtu3_regset *mregs; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci mregs = devm_kzalloc(mtu->dev, sizeof(*mregs), GFP_KERNEL); 1318c2ecf20Sopenharmony_ci if (!mregs) 1328c2ecf20Sopenharmony_ci return; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci sprintf(mregs->name, "%s", name); 1358c2ecf20Sopenharmony_ci regset = &mregs->regset; 1368c2ecf20Sopenharmony_ci regset->regs = regs; 1378c2ecf20Sopenharmony_ci regset->nregs = nregs; 1388c2ecf20Sopenharmony_ci regset->base = base; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci debugfs_create_regset32(mregs->name, 0444, parent, regset); 1418c2ecf20Sopenharmony_ci} 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_cistatic void mtu3_debugfs_ep_regset(struct mtu3 *mtu, struct mtu3_ep *mep, 1448c2ecf20Sopenharmony_ci struct dentry *parent) 1458c2ecf20Sopenharmony_ci{ 1468c2ecf20Sopenharmony_ci struct debugfs_reg32 *regs; 1478c2ecf20Sopenharmony_ci int epnum = mep->epnum; 1488c2ecf20Sopenharmony_ci int in = mep->is_in; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci regs = devm_kcalloc(mtu->dev, 7, sizeof(*regs), GFP_KERNEL); 1518c2ecf20Sopenharmony_ci if (!regs) 1528c2ecf20Sopenharmony_ci return; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci regs[0].name = in ? "TCR0" : "RCR0"; 1558c2ecf20Sopenharmony_ci regs[0].offset = in ? MU3D_EP_TXCR0(epnum) : MU3D_EP_RXCR0(epnum); 1568c2ecf20Sopenharmony_ci regs[1].name = in ? "TCR1" : "RCR1"; 1578c2ecf20Sopenharmony_ci regs[1].offset = in ? MU3D_EP_TXCR1(epnum) : MU3D_EP_RXCR1(epnum); 1588c2ecf20Sopenharmony_ci regs[2].name = in ? "TCR2" : "RCR2"; 1598c2ecf20Sopenharmony_ci regs[2].offset = in ? MU3D_EP_TXCR2(epnum) : MU3D_EP_RXCR2(epnum); 1608c2ecf20Sopenharmony_ci regs[3].name = in ? "TQHIAR" : "RQHIAR"; 1618c2ecf20Sopenharmony_ci regs[3].offset = in ? USB_QMU_TQHIAR(epnum) : USB_QMU_RQHIAR(epnum); 1628c2ecf20Sopenharmony_ci regs[4].name = in ? "TQCSR" : "RQCSR"; 1638c2ecf20Sopenharmony_ci regs[4].offset = in ? USB_QMU_TQCSR(epnum) : USB_QMU_RQCSR(epnum); 1648c2ecf20Sopenharmony_ci regs[5].name = in ? "TQSAR" : "RQSAR"; 1658c2ecf20Sopenharmony_ci regs[5].offset = in ? USB_QMU_TQSAR(epnum) : USB_QMU_RQSAR(epnum); 1668c2ecf20Sopenharmony_ci regs[6].name = in ? "TQCPR" : "RQCPR"; 1678c2ecf20Sopenharmony_ci regs[6].offset = in ? USB_QMU_TQCPR(epnum) : USB_QMU_RQCPR(epnum); 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci mtu3_debugfs_regset(mtu, mtu->mac_base, regs, 7, "ep-regs", parent); 1708c2ecf20Sopenharmony_ci} 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_cistatic int mtu3_ep_info_show(struct seq_file *sf, void *unused) 1738c2ecf20Sopenharmony_ci{ 1748c2ecf20Sopenharmony_ci struct mtu3_ep *mep = sf->private; 1758c2ecf20Sopenharmony_ci struct mtu3 *mtu = mep->mtu; 1768c2ecf20Sopenharmony_ci unsigned long flags; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci spin_lock_irqsave(&mtu->lock, flags); 1798c2ecf20Sopenharmony_ci seq_printf(sf, "ep - type:%d, maxp:%d, slot:%d, flags:%x\n", 1808c2ecf20Sopenharmony_ci mep->type, mep->maxp, mep->slot, mep->flags); 1818c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&mtu->lock, flags); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci return 0; 1848c2ecf20Sopenharmony_ci} 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_cistatic int mtu3_fifo_show(struct seq_file *sf, void *unused) 1878c2ecf20Sopenharmony_ci{ 1888c2ecf20Sopenharmony_ci struct mtu3_ep *mep = sf->private; 1898c2ecf20Sopenharmony_ci struct mtu3 *mtu = mep->mtu; 1908c2ecf20Sopenharmony_ci unsigned long flags; 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci spin_lock_irqsave(&mtu->lock, flags); 1938c2ecf20Sopenharmony_ci seq_printf(sf, "fifo - seg_size:%d, addr:%d, size:%d\n", 1948c2ecf20Sopenharmony_ci mep->fifo_seg_size, mep->fifo_addr, mep->fifo_size); 1958c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&mtu->lock, flags); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci return 0; 1988c2ecf20Sopenharmony_ci} 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_cistatic int mtu3_qmu_ring_show(struct seq_file *sf, void *unused) 2018c2ecf20Sopenharmony_ci{ 2028c2ecf20Sopenharmony_ci struct mtu3_ep *mep = sf->private; 2038c2ecf20Sopenharmony_ci struct mtu3 *mtu = mep->mtu; 2048c2ecf20Sopenharmony_ci struct mtu3_gpd_ring *ring; 2058c2ecf20Sopenharmony_ci unsigned long flags; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci ring = &mep->gpd_ring; 2088c2ecf20Sopenharmony_ci spin_lock_irqsave(&mtu->lock, flags); 2098c2ecf20Sopenharmony_ci seq_printf(sf, 2108c2ecf20Sopenharmony_ci "qmu-ring - dma:%pad, start:%p, end:%p, enq:%p, dep:%p\n", 2118c2ecf20Sopenharmony_ci &ring->dma, ring->start, ring->end, 2128c2ecf20Sopenharmony_ci ring->enqueue, ring->dequeue); 2138c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&mtu->lock, flags); 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci return 0; 2168c2ecf20Sopenharmony_ci} 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_cistatic int mtu3_qmu_gpd_show(struct seq_file *sf, void *unused) 2198c2ecf20Sopenharmony_ci{ 2208c2ecf20Sopenharmony_ci struct mtu3_ep *mep = sf->private; 2218c2ecf20Sopenharmony_ci struct mtu3 *mtu = mep->mtu; 2228c2ecf20Sopenharmony_ci struct mtu3_gpd_ring *ring; 2238c2ecf20Sopenharmony_ci struct qmu_gpd *gpd; 2248c2ecf20Sopenharmony_ci dma_addr_t dma; 2258c2ecf20Sopenharmony_ci unsigned long flags; 2268c2ecf20Sopenharmony_ci int i; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci spin_lock_irqsave(&mtu->lock, flags); 2298c2ecf20Sopenharmony_ci ring = &mep->gpd_ring; 2308c2ecf20Sopenharmony_ci gpd = ring->start; 2318c2ecf20Sopenharmony_ci if (!gpd || !(mep->flags & MTU3_EP_ENABLED)) { 2328c2ecf20Sopenharmony_ci seq_puts(sf, "empty!\n"); 2338c2ecf20Sopenharmony_ci goto out; 2348c2ecf20Sopenharmony_ci } 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci for (i = 0; i < MAX_GPD_NUM; i++, gpd++) { 2378c2ecf20Sopenharmony_ci dma = ring->dma + i * sizeof(*gpd); 2388c2ecf20Sopenharmony_ci seq_printf(sf, "gpd.%03d -> %pad, %p: %08x %08x %08x %08x\n", 2398c2ecf20Sopenharmony_ci i, &dma, gpd, gpd->dw0_info, gpd->next_gpd, 2408c2ecf20Sopenharmony_ci gpd->buffer, gpd->dw3_info); 2418c2ecf20Sopenharmony_ci } 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ciout: 2448c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&mtu->lock, flags); 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci return 0; 2478c2ecf20Sopenharmony_ci} 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_cistatic const struct mtu3_file_map mtu3_ep_files[] = { 2508c2ecf20Sopenharmony_ci {"ep-info", mtu3_ep_info_show, }, 2518c2ecf20Sopenharmony_ci {"fifo", mtu3_fifo_show, }, 2528c2ecf20Sopenharmony_ci {"qmu-ring", mtu3_qmu_ring_show, }, 2538c2ecf20Sopenharmony_ci {"qmu-gpd", mtu3_qmu_gpd_show, }, 2548c2ecf20Sopenharmony_ci}; 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_cistatic int mtu3_ep_open(struct inode *inode, struct file *file) 2578c2ecf20Sopenharmony_ci{ 2588c2ecf20Sopenharmony_ci const char *file_name = file_dentry(file)->d_iname; 2598c2ecf20Sopenharmony_ci const struct mtu3_file_map *f_map; 2608c2ecf20Sopenharmony_ci int i; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mtu3_ep_files); i++) { 2638c2ecf20Sopenharmony_ci f_map = &mtu3_ep_files[i]; 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci if (strcmp(f_map->name, file_name) == 0) 2668c2ecf20Sopenharmony_ci break; 2678c2ecf20Sopenharmony_ci } 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci return single_open(file, f_map->show, inode->i_private); 2708c2ecf20Sopenharmony_ci} 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_cistatic const struct file_operations mtu3_ep_fops = { 2738c2ecf20Sopenharmony_ci .open = mtu3_ep_open, 2748c2ecf20Sopenharmony_ci .read = seq_read, 2758c2ecf20Sopenharmony_ci .llseek = seq_lseek, 2768c2ecf20Sopenharmony_ci .release = single_release, 2778c2ecf20Sopenharmony_ci}; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_cistatic const struct debugfs_reg32 mtu3_prb_regs[] = { 2808c2ecf20Sopenharmony_ci dump_prb_reg("enable", U3D_SSUSB_PRB_CTRL0), 2818c2ecf20Sopenharmony_ci dump_prb_reg("byte-sell", U3D_SSUSB_PRB_CTRL1), 2828c2ecf20Sopenharmony_ci dump_prb_reg("byte-selh", U3D_SSUSB_PRB_CTRL2), 2838c2ecf20Sopenharmony_ci dump_prb_reg("module-sel", U3D_SSUSB_PRB_CTRL3), 2848c2ecf20Sopenharmony_ci dump_prb_reg("sw-out", U3D_SSUSB_PRB_CTRL4), 2858c2ecf20Sopenharmony_ci dump_prb_reg("data", U3D_SSUSB_PRB_CTRL5), 2868c2ecf20Sopenharmony_ci}; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_cistatic int mtu3_probe_show(struct seq_file *sf, void *unused) 2898c2ecf20Sopenharmony_ci{ 2908c2ecf20Sopenharmony_ci const char *file_name = file_dentry(sf->file)->d_iname; 2918c2ecf20Sopenharmony_ci struct mtu3 *mtu = sf->private; 2928c2ecf20Sopenharmony_ci const struct debugfs_reg32 *regs; 2938c2ecf20Sopenharmony_ci int i; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mtu3_prb_regs); i++) { 2968c2ecf20Sopenharmony_ci regs = &mtu3_prb_regs[i]; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci if (strcmp(regs->name, file_name) == 0) 2998c2ecf20Sopenharmony_ci break; 3008c2ecf20Sopenharmony_ci } 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci seq_printf(sf, "0x%04x - 0x%08x\n", (u32)regs->offset, 3038c2ecf20Sopenharmony_ci mtu3_readl(mtu->ippc_base, (u32)regs->offset)); 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci return 0; 3068c2ecf20Sopenharmony_ci} 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_cistatic int mtu3_probe_open(struct inode *inode, struct file *file) 3098c2ecf20Sopenharmony_ci{ 3108c2ecf20Sopenharmony_ci return single_open(file, mtu3_probe_show, inode->i_private); 3118c2ecf20Sopenharmony_ci} 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_cistatic ssize_t mtu3_probe_write(struct file *file, const char __user *ubuf, 3148c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 3158c2ecf20Sopenharmony_ci{ 3168c2ecf20Sopenharmony_ci const char *file_name = file_dentry(file)->d_iname; 3178c2ecf20Sopenharmony_ci struct seq_file *sf = file->private_data; 3188c2ecf20Sopenharmony_ci struct mtu3 *mtu = sf->private; 3198c2ecf20Sopenharmony_ci const struct debugfs_reg32 *regs; 3208c2ecf20Sopenharmony_ci char buf[32]; 3218c2ecf20Sopenharmony_ci u32 val; 3228c2ecf20Sopenharmony_ci int i; 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) 3258c2ecf20Sopenharmony_ci return -EFAULT; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci if (kstrtou32(buf, 0, &val)) 3288c2ecf20Sopenharmony_ci return -EINVAL; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mtu3_prb_regs); i++) { 3318c2ecf20Sopenharmony_ci regs = &mtu3_prb_regs[i]; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci if (strcmp(regs->name, file_name) == 0) 3348c2ecf20Sopenharmony_ci break; 3358c2ecf20Sopenharmony_ci } 3368c2ecf20Sopenharmony_ci mtu3_writel(mtu->ippc_base, (u32)regs->offset, val); 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci return count; 3398c2ecf20Sopenharmony_ci} 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_cistatic const struct file_operations mtu3_probe_fops = { 3428c2ecf20Sopenharmony_ci .open = mtu3_probe_open, 3438c2ecf20Sopenharmony_ci .write = mtu3_probe_write, 3448c2ecf20Sopenharmony_ci .read = seq_read, 3458c2ecf20Sopenharmony_ci .llseek = seq_lseek, 3468c2ecf20Sopenharmony_ci .release = single_release, 3478c2ecf20Sopenharmony_ci}; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_cistatic void mtu3_debugfs_create_prb_files(struct mtu3 *mtu) 3508c2ecf20Sopenharmony_ci{ 3518c2ecf20Sopenharmony_ci struct ssusb_mtk *ssusb = mtu->ssusb; 3528c2ecf20Sopenharmony_ci const struct debugfs_reg32 *regs; 3538c2ecf20Sopenharmony_ci struct dentry *dir_prb; 3548c2ecf20Sopenharmony_ci int i; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci dir_prb = debugfs_create_dir("probe", ssusb->dbgfs_root); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mtu3_prb_regs); i++) { 3598c2ecf20Sopenharmony_ci regs = &mtu3_prb_regs[i]; 3608c2ecf20Sopenharmony_ci debugfs_create_file(regs->name, 0644, dir_prb, 3618c2ecf20Sopenharmony_ci mtu, &mtu3_probe_fops); 3628c2ecf20Sopenharmony_ci } 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci mtu3_debugfs_regset(mtu, mtu->ippc_base, mtu3_prb_regs, 3658c2ecf20Sopenharmony_ci ARRAY_SIZE(mtu3_prb_regs), "regs", dir_prb); 3668c2ecf20Sopenharmony_ci} 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_cistatic void mtu3_debugfs_create_ep_dir(struct mtu3_ep *mep, 3698c2ecf20Sopenharmony_ci struct dentry *parent) 3708c2ecf20Sopenharmony_ci{ 3718c2ecf20Sopenharmony_ci const struct mtu3_file_map *files; 3728c2ecf20Sopenharmony_ci struct dentry *dir_ep; 3738c2ecf20Sopenharmony_ci int i; 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci dir_ep = debugfs_create_dir(mep->name, parent); 3768c2ecf20Sopenharmony_ci mtu3_debugfs_ep_regset(mep->mtu, mep, dir_ep); 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mtu3_ep_files); i++) { 3798c2ecf20Sopenharmony_ci files = &mtu3_ep_files[i]; 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci debugfs_create_file(files->name, 0444, dir_ep, 3828c2ecf20Sopenharmony_ci mep, &mtu3_ep_fops); 3838c2ecf20Sopenharmony_ci } 3848c2ecf20Sopenharmony_ci} 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_cistatic void mtu3_debugfs_create_ep_dirs(struct mtu3 *mtu) 3878c2ecf20Sopenharmony_ci{ 3888c2ecf20Sopenharmony_ci struct ssusb_mtk *ssusb = mtu->ssusb; 3898c2ecf20Sopenharmony_ci struct dentry *dir_eps; 3908c2ecf20Sopenharmony_ci int i; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci dir_eps = debugfs_create_dir("eps", ssusb->dbgfs_root); 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci for (i = 1; i < mtu->num_eps; i++) { 3958c2ecf20Sopenharmony_ci mtu3_debugfs_create_ep_dir(mtu->in_eps + i, dir_eps); 3968c2ecf20Sopenharmony_ci mtu3_debugfs_create_ep_dir(mtu->out_eps + i, dir_eps); 3978c2ecf20Sopenharmony_ci } 3988c2ecf20Sopenharmony_ci} 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_civoid ssusb_dev_debugfs_init(struct ssusb_mtk *ssusb) 4018c2ecf20Sopenharmony_ci{ 4028c2ecf20Sopenharmony_ci struct mtu3 *mtu = ssusb->u3d; 4038c2ecf20Sopenharmony_ci struct dentry *dir_regs; 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci dir_regs = debugfs_create_dir("regs", ssusb->dbgfs_root); 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci mtu3_debugfs_regset(mtu, mtu->ippc_base, 4088c2ecf20Sopenharmony_ci mtu3_ippc_regs, ARRAY_SIZE(mtu3_ippc_regs), 4098c2ecf20Sopenharmony_ci "reg-ippc", dir_regs); 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci mtu3_debugfs_regset(mtu, mtu->mac_base, 4128c2ecf20Sopenharmony_ci mtu3_dev_regs, ARRAY_SIZE(mtu3_dev_regs), 4138c2ecf20Sopenharmony_ci "reg-dev", dir_regs); 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci mtu3_debugfs_regset(mtu, mtu->mac_base, 4168c2ecf20Sopenharmony_ci mtu3_csr_regs, ARRAY_SIZE(mtu3_csr_regs), 4178c2ecf20Sopenharmony_ci "reg-csr", dir_regs); 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci mtu3_debugfs_create_ep_dirs(mtu); 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci mtu3_debugfs_create_prb_files(mtu); 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci debugfs_create_file("link-state", 0444, ssusb->dbgfs_root, 4248c2ecf20Sopenharmony_ci mtu, &mtu3_link_state_fops); 4258c2ecf20Sopenharmony_ci debugfs_create_file("ep-used", 0444, ssusb->dbgfs_root, 4268c2ecf20Sopenharmony_ci mtu, &mtu3_ep_used_fops); 4278c2ecf20Sopenharmony_ci} 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_cistatic int ssusb_mode_show(struct seq_file *sf, void *unused) 4308c2ecf20Sopenharmony_ci{ 4318c2ecf20Sopenharmony_ci struct ssusb_mtk *ssusb = sf->private; 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci seq_printf(sf, "current mode: %s(%s drd)\n(echo device/host)\n", 4348c2ecf20Sopenharmony_ci ssusb->is_host ? "host" : "device", 4358c2ecf20Sopenharmony_ci ssusb->otg_switch.manual_drd_enabled ? "manual" : "auto"); 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci return 0; 4388c2ecf20Sopenharmony_ci} 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_cistatic int ssusb_mode_open(struct inode *inode, struct file *file) 4418c2ecf20Sopenharmony_ci{ 4428c2ecf20Sopenharmony_ci return single_open(file, ssusb_mode_show, inode->i_private); 4438c2ecf20Sopenharmony_ci} 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_cistatic ssize_t ssusb_mode_write(struct file *file, const char __user *ubuf, 4468c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 4478c2ecf20Sopenharmony_ci{ 4488c2ecf20Sopenharmony_ci struct seq_file *sf = file->private_data; 4498c2ecf20Sopenharmony_ci struct ssusb_mtk *ssusb = sf->private; 4508c2ecf20Sopenharmony_ci char buf[16]; 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) 4538c2ecf20Sopenharmony_ci return -EFAULT; 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci if (!strncmp(buf, "host", 4) && !ssusb->is_host) { 4568c2ecf20Sopenharmony_ci ssusb_mode_switch(ssusb, 1); 4578c2ecf20Sopenharmony_ci } else if (!strncmp(buf, "device", 6) && ssusb->is_host) { 4588c2ecf20Sopenharmony_ci ssusb_mode_switch(ssusb, 0); 4598c2ecf20Sopenharmony_ci } else { 4608c2ecf20Sopenharmony_ci dev_err(ssusb->dev, "wrong or duplicated setting\n"); 4618c2ecf20Sopenharmony_ci return -EINVAL; 4628c2ecf20Sopenharmony_ci } 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci return count; 4658c2ecf20Sopenharmony_ci} 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_cistatic const struct file_operations ssusb_mode_fops = { 4688c2ecf20Sopenharmony_ci .open = ssusb_mode_open, 4698c2ecf20Sopenharmony_ci .write = ssusb_mode_write, 4708c2ecf20Sopenharmony_ci .read = seq_read, 4718c2ecf20Sopenharmony_ci .llseek = seq_lseek, 4728c2ecf20Sopenharmony_ci .release = single_release, 4738c2ecf20Sopenharmony_ci}; 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_cistatic int ssusb_vbus_show(struct seq_file *sf, void *unused) 4768c2ecf20Sopenharmony_ci{ 4778c2ecf20Sopenharmony_ci struct ssusb_mtk *ssusb = sf->private; 4788c2ecf20Sopenharmony_ci struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci seq_printf(sf, "vbus state: %s\n(echo on/off)\n", 4818c2ecf20Sopenharmony_ci regulator_is_enabled(otg_sx->vbus) ? "on" : "off"); 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci return 0; 4848c2ecf20Sopenharmony_ci} 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_cistatic int ssusb_vbus_open(struct inode *inode, struct file *file) 4878c2ecf20Sopenharmony_ci{ 4888c2ecf20Sopenharmony_ci return single_open(file, ssusb_vbus_show, inode->i_private); 4898c2ecf20Sopenharmony_ci} 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_cistatic ssize_t ssusb_vbus_write(struct file *file, const char __user *ubuf, 4928c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 4938c2ecf20Sopenharmony_ci{ 4948c2ecf20Sopenharmony_ci struct seq_file *sf = file->private_data; 4958c2ecf20Sopenharmony_ci struct ssusb_mtk *ssusb = sf->private; 4968c2ecf20Sopenharmony_ci struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; 4978c2ecf20Sopenharmony_ci char buf[16]; 4988c2ecf20Sopenharmony_ci bool enable; 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) 5018c2ecf20Sopenharmony_ci return -EFAULT; 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci if (kstrtobool(buf, &enable)) { 5048c2ecf20Sopenharmony_ci dev_err(ssusb->dev, "wrong setting\n"); 5058c2ecf20Sopenharmony_ci return -EINVAL; 5068c2ecf20Sopenharmony_ci } 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci ssusb_set_vbus(otg_sx, enable); 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci return count; 5118c2ecf20Sopenharmony_ci} 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_cistatic const struct file_operations ssusb_vbus_fops = { 5148c2ecf20Sopenharmony_ci .open = ssusb_vbus_open, 5158c2ecf20Sopenharmony_ci .write = ssusb_vbus_write, 5168c2ecf20Sopenharmony_ci .read = seq_read, 5178c2ecf20Sopenharmony_ci .llseek = seq_lseek, 5188c2ecf20Sopenharmony_ci .release = single_release, 5198c2ecf20Sopenharmony_ci}; 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_civoid ssusb_dr_debugfs_init(struct ssusb_mtk *ssusb) 5228c2ecf20Sopenharmony_ci{ 5238c2ecf20Sopenharmony_ci struct dentry *root = ssusb->dbgfs_root; 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci debugfs_create_file("mode", 0644, root, ssusb, &ssusb_mode_fops); 5268c2ecf20Sopenharmony_ci debugfs_create_file("vbus", 0644, root, ssusb, &ssusb_vbus_fops); 5278c2ecf20Sopenharmony_ci} 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_civoid ssusb_debugfs_create_root(struct ssusb_mtk *ssusb) 5308c2ecf20Sopenharmony_ci{ 5318c2ecf20Sopenharmony_ci ssusb->dbgfs_root = 5328c2ecf20Sopenharmony_ci debugfs_create_dir(dev_name(ssusb->dev), usb_debug_root); 5338c2ecf20Sopenharmony_ci} 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_civoid ssusb_debugfs_remove_root(struct ssusb_mtk *ssusb) 5368c2ecf20Sopenharmony_ci{ 5378c2ecf20Sopenharmony_ci debugfs_remove_recursive(ssusb->dbgfs_root); 5388c2ecf20Sopenharmony_ci ssusb->dbgfs_root = NULL; 5398c2ecf20Sopenharmony_ci} 540