162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * mtu3_debugfs.c - debugfs interface 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2019 MediaTek Inc. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Author: Chunfeng Yun <chunfeng.yun@mediatek.com> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/uaccess.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include "mtu3.h" 1362306a36Sopenharmony_ci#include "mtu3_dr.h" 1462306a36Sopenharmony_ci#include "mtu3_debug.h" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#define dump_register(nm) \ 1762306a36Sopenharmony_ci{ \ 1862306a36Sopenharmony_ci .name = __stringify(nm), \ 1962306a36Sopenharmony_ci .offset = U3D_ ##nm, \ 2062306a36Sopenharmony_ci} 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#define dump_prb_reg(nm, os) \ 2362306a36Sopenharmony_ci{ \ 2462306a36Sopenharmony_ci .name = nm, \ 2562306a36Sopenharmony_ci .offset = os, \ 2662306a36Sopenharmony_ci} 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic const struct debugfs_reg32 mtu3_ippc_regs[] = { 2962306a36Sopenharmony_ci dump_register(SSUSB_IP_PW_CTRL0), 3062306a36Sopenharmony_ci dump_register(SSUSB_IP_PW_CTRL1), 3162306a36Sopenharmony_ci dump_register(SSUSB_IP_PW_CTRL2), 3262306a36Sopenharmony_ci dump_register(SSUSB_IP_PW_CTRL3), 3362306a36Sopenharmony_ci dump_register(SSUSB_IP_PW_STS1), 3462306a36Sopenharmony_ci dump_register(SSUSB_OTG_STS), 3562306a36Sopenharmony_ci dump_register(SSUSB_IP_XHCI_CAP), 3662306a36Sopenharmony_ci dump_register(SSUSB_IP_DEV_CAP), 3762306a36Sopenharmony_ci dump_register(SSUSB_U3_CTRL_0P), 3862306a36Sopenharmony_ci dump_register(SSUSB_U2_CTRL_0P), 3962306a36Sopenharmony_ci dump_register(SSUSB_HW_ID), 4062306a36Sopenharmony_ci dump_register(SSUSB_HW_SUB_ID), 4162306a36Sopenharmony_ci dump_register(SSUSB_IP_SPARE0), 4262306a36Sopenharmony_ci}; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistatic const struct debugfs_reg32 mtu3_dev_regs[] = { 4562306a36Sopenharmony_ci dump_register(LV1ISR), 4662306a36Sopenharmony_ci dump_register(LV1IER), 4762306a36Sopenharmony_ci dump_register(EPISR), 4862306a36Sopenharmony_ci dump_register(EPIER), 4962306a36Sopenharmony_ci dump_register(EP0CSR), 5062306a36Sopenharmony_ci dump_register(RXCOUNT0), 5162306a36Sopenharmony_ci dump_register(QISAR0), 5262306a36Sopenharmony_ci dump_register(QIER0), 5362306a36Sopenharmony_ci dump_register(QISAR1), 5462306a36Sopenharmony_ci dump_register(QIER1), 5562306a36Sopenharmony_ci dump_register(CAP_EPNTXFFSZ), 5662306a36Sopenharmony_ci dump_register(CAP_EPNRXFFSZ), 5762306a36Sopenharmony_ci dump_register(CAP_EPINFO), 5862306a36Sopenharmony_ci dump_register(MISC_CTRL), 5962306a36Sopenharmony_ci}; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cistatic const struct debugfs_reg32 mtu3_csr_regs[] = { 6262306a36Sopenharmony_ci dump_register(DEVICE_CONF), 6362306a36Sopenharmony_ci dump_register(DEV_LINK_INTR_ENABLE), 6462306a36Sopenharmony_ci dump_register(DEV_LINK_INTR), 6562306a36Sopenharmony_ci dump_register(LTSSM_CTRL), 6662306a36Sopenharmony_ci dump_register(USB3_CONFIG), 6762306a36Sopenharmony_ci dump_register(LINK_STATE_MACHINE), 6862306a36Sopenharmony_ci dump_register(LTSSM_INTR_ENABLE), 6962306a36Sopenharmony_ci dump_register(LTSSM_INTR), 7062306a36Sopenharmony_ci dump_register(U3U2_SWITCH_CTRL), 7162306a36Sopenharmony_ci dump_register(POWER_MANAGEMENT), 7262306a36Sopenharmony_ci dump_register(DEVICE_CONTROL), 7362306a36Sopenharmony_ci dump_register(COMMON_USB_INTR_ENABLE), 7462306a36Sopenharmony_ci dump_register(COMMON_USB_INTR), 7562306a36Sopenharmony_ci dump_register(USB20_MISC_CONTROL), 7662306a36Sopenharmony_ci dump_register(USB20_OPSTATE), 7762306a36Sopenharmony_ci}; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_cistatic int mtu3_link_state_show(struct seq_file *sf, void *unused) 8062306a36Sopenharmony_ci{ 8162306a36Sopenharmony_ci struct mtu3 *mtu = sf->private; 8262306a36Sopenharmony_ci void __iomem *mbase = mtu->mac_base; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci seq_printf(sf, "opstate: %#x, ltssm: %#x\n", 8562306a36Sopenharmony_ci mtu3_readl(mbase, U3D_USB20_OPSTATE), 8662306a36Sopenharmony_ci LTSSM_STATE(mtu3_readl(mbase, U3D_LINK_STATE_MACHINE))); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci return 0; 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistatic int mtu3_ep_used_show(struct seq_file *sf, void *unused) 9262306a36Sopenharmony_ci{ 9362306a36Sopenharmony_ci struct mtu3 *mtu = sf->private; 9462306a36Sopenharmony_ci struct mtu3_ep *mep; 9562306a36Sopenharmony_ci unsigned long flags; 9662306a36Sopenharmony_ci int used = 0; 9762306a36Sopenharmony_ci int i; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci spin_lock_irqsave(&mtu->lock, flags); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci for (i = 0; i < mtu->num_eps; i++) { 10262306a36Sopenharmony_ci mep = mtu->in_eps + i; 10362306a36Sopenharmony_ci if (mep->flags & MTU3_EP_ENABLED) { 10462306a36Sopenharmony_ci seq_printf(sf, "%s - type: %s\n", mep->name, usb_ep_type_string(mep->type)); 10562306a36Sopenharmony_ci used++; 10662306a36Sopenharmony_ci } 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci mep = mtu->out_eps + i; 10962306a36Sopenharmony_ci if (mep->flags & MTU3_EP_ENABLED) { 11062306a36Sopenharmony_ci seq_printf(sf, "%s - type: %s\n", mep->name, usb_ep_type_string(mep->type)); 11162306a36Sopenharmony_ci used++; 11262306a36Sopenharmony_ci } 11362306a36Sopenharmony_ci } 11462306a36Sopenharmony_ci seq_printf(sf, "total used: %d eps\n", used); 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci spin_unlock_irqrestore(&mtu->lock, flags); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci return 0; 11962306a36Sopenharmony_ci} 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(mtu3_link_state); 12262306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(mtu3_ep_used); 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cistatic void mtu3_debugfs_regset(struct mtu3 *mtu, void __iomem *base, 12562306a36Sopenharmony_ci const struct debugfs_reg32 *regs, size_t nregs, 12662306a36Sopenharmony_ci const char *name, struct dentry *parent) 12762306a36Sopenharmony_ci{ 12862306a36Sopenharmony_ci struct debugfs_regset32 *regset; 12962306a36Sopenharmony_ci struct mtu3_regset *mregs; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci mregs = devm_kzalloc(mtu->dev, sizeof(*mregs), GFP_KERNEL); 13262306a36Sopenharmony_ci if (!mregs) 13362306a36Sopenharmony_ci return; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci sprintf(mregs->name, "%s", name); 13662306a36Sopenharmony_ci regset = &mregs->regset; 13762306a36Sopenharmony_ci regset->regs = regs; 13862306a36Sopenharmony_ci regset->nregs = nregs; 13962306a36Sopenharmony_ci regset->base = base; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci debugfs_create_regset32(mregs->name, 0444, parent, regset); 14262306a36Sopenharmony_ci} 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_cistatic void mtu3_debugfs_ep_regset(struct mtu3 *mtu, struct mtu3_ep *mep, 14562306a36Sopenharmony_ci struct dentry *parent) 14662306a36Sopenharmony_ci{ 14762306a36Sopenharmony_ci struct debugfs_reg32 *regs; 14862306a36Sopenharmony_ci int epnum = mep->epnum; 14962306a36Sopenharmony_ci int in = mep->is_in; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci regs = devm_kcalloc(mtu->dev, 7, sizeof(*regs), GFP_KERNEL); 15262306a36Sopenharmony_ci if (!regs) 15362306a36Sopenharmony_ci return; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci regs[0].name = in ? "TCR0" : "RCR0"; 15662306a36Sopenharmony_ci regs[0].offset = in ? MU3D_EP_TXCR0(epnum) : MU3D_EP_RXCR0(epnum); 15762306a36Sopenharmony_ci regs[1].name = in ? "TCR1" : "RCR1"; 15862306a36Sopenharmony_ci regs[1].offset = in ? MU3D_EP_TXCR1(epnum) : MU3D_EP_RXCR1(epnum); 15962306a36Sopenharmony_ci regs[2].name = in ? "TCR2" : "RCR2"; 16062306a36Sopenharmony_ci regs[2].offset = in ? MU3D_EP_TXCR2(epnum) : MU3D_EP_RXCR2(epnum); 16162306a36Sopenharmony_ci regs[3].name = in ? "TQHIAR" : "RQHIAR"; 16262306a36Sopenharmony_ci regs[3].offset = in ? USB_QMU_TQHIAR(epnum) : USB_QMU_RQHIAR(epnum); 16362306a36Sopenharmony_ci regs[4].name = in ? "TQCSR" : "RQCSR"; 16462306a36Sopenharmony_ci regs[4].offset = in ? USB_QMU_TQCSR(epnum) : USB_QMU_RQCSR(epnum); 16562306a36Sopenharmony_ci regs[5].name = in ? "TQSAR" : "RQSAR"; 16662306a36Sopenharmony_ci regs[5].offset = in ? USB_QMU_TQSAR(epnum) : USB_QMU_RQSAR(epnum); 16762306a36Sopenharmony_ci regs[6].name = in ? "TQCPR" : "RQCPR"; 16862306a36Sopenharmony_ci regs[6].offset = in ? USB_QMU_TQCPR(epnum) : USB_QMU_RQCPR(epnum); 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci mtu3_debugfs_regset(mtu, mtu->mac_base, regs, 7, "ep-regs", parent); 17162306a36Sopenharmony_ci} 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_cistatic int mtu3_ep_info_show(struct seq_file *sf, void *unused) 17462306a36Sopenharmony_ci{ 17562306a36Sopenharmony_ci struct mtu3_ep *mep = sf->private; 17662306a36Sopenharmony_ci struct mtu3 *mtu = mep->mtu; 17762306a36Sopenharmony_ci unsigned long flags; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci spin_lock_irqsave(&mtu->lock, flags); 18062306a36Sopenharmony_ci seq_printf(sf, "ep - type:%s, maxp:%d, slot:%d, flags:%x\n", 18162306a36Sopenharmony_ci usb_ep_type_string(mep->type), mep->maxp, mep->slot, mep->flags); 18262306a36Sopenharmony_ci spin_unlock_irqrestore(&mtu->lock, flags); 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci return 0; 18562306a36Sopenharmony_ci} 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_cistatic int mtu3_fifo_show(struct seq_file *sf, void *unused) 18862306a36Sopenharmony_ci{ 18962306a36Sopenharmony_ci struct mtu3_ep *mep = sf->private; 19062306a36Sopenharmony_ci struct mtu3 *mtu = mep->mtu; 19162306a36Sopenharmony_ci unsigned long flags; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci spin_lock_irqsave(&mtu->lock, flags); 19462306a36Sopenharmony_ci seq_printf(sf, "fifo - seg_size:%d, addr:%d, size:%d\n", 19562306a36Sopenharmony_ci mep->fifo_seg_size, mep->fifo_addr, mep->fifo_size); 19662306a36Sopenharmony_ci spin_unlock_irqrestore(&mtu->lock, flags); 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci return 0; 19962306a36Sopenharmony_ci} 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_cistatic int mtu3_qmu_ring_show(struct seq_file *sf, void *unused) 20262306a36Sopenharmony_ci{ 20362306a36Sopenharmony_ci struct mtu3_ep *mep = sf->private; 20462306a36Sopenharmony_ci struct mtu3 *mtu = mep->mtu; 20562306a36Sopenharmony_ci struct mtu3_gpd_ring *ring; 20662306a36Sopenharmony_ci unsigned long flags; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci ring = &mep->gpd_ring; 20962306a36Sopenharmony_ci spin_lock_irqsave(&mtu->lock, flags); 21062306a36Sopenharmony_ci seq_printf(sf, 21162306a36Sopenharmony_ci "qmu-ring - dma:%pad, start:%p, end:%p, enq:%p, dep:%p\n", 21262306a36Sopenharmony_ci &ring->dma, ring->start, ring->end, 21362306a36Sopenharmony_ci ring->enqueue, ring->dequeue); 21462306a36Sopenharmony_ci spin_unlock_irqrestore(&mtu->lock, flags); 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci return 0; 21762306a36Sopenharmony_ci} 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_cistatic int mtu3_qmu_gpd_show(struct seq_file *sf, void *unused) 22062306a36Sopenharmony_ci{ 22162306a36Sopenharmony_ci struct mtu3_ep *mep = sf->private; 22262306a36Sopenharmony_ci struct mtu3 *mtu = mep->mtu; 22362306a36Sopenharmony_ci struct mtu3_gpd_ring *ring; 22462306a36Sopenharmony_ci struct qmu_gpd *gpd; 22562306a36Sopenharmony_ci dma_addr_t dma; 22662306a36Sopenharmony_ci unsigned long flags; 22762306a36Sopenharmony_ci int i; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci spin_lock_irqsave(&mtu->lock, flags); 23062306a36Sopenharmony_ci ring = &mep->gpd_ring; 23162306a36Sopenharmony_ci gpd = ring->start; 23262306a36Sopenharmony_ci if (!gpd || !(mep->flags & MTU3_EP_ENABLED)) { 23362306a36Sopenharmony_ci seq_puts(sf, "empty!\n"); 23462306a36Sopenharmony_ci goto out; 23562306a36Sopenharmony_ci } 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci for (i = 0; i < MAX_GPD_NUM; i++, gpd++) { 23862306a36Sopenharmony_ci dma = ring->dma + i * sizeof(*gpd); 23962306a36Sopenharmony_ci seq_printf(sf, "gpd.%03d -> %pad, %p: %08x %08x %08x %08x\n", 24062306a36Sopenharmony_ci i, &dma, gpd, gpd->dw0_info, gpd->next_gpd, 24162306a36Sopenharmony_ci gpd->buffer, gpd->dw3_info); 24262306a36Sopenharmony_ci } 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ciout: 24562306a36Sopenharmony_ci spin_unlock_irqrestore(&mtu->lock, flags); 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci return 0; 24862306a36Sopenharmony_ci} 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_cistatic const struct mtu3_file_map mtu3_ep_files[] = { 25162306a36Sopenharmony_ci {"ep-info", mtu3_ep_info_show, }, 25262306a36Sopenharmony_ci {"fifo", mtu3_fifo_show, }, 25362306a36Sopenharmony_ci {"qmu-ring", mtu3_qmu_ring_show, }, 25462306a36Sopenharmony_ci {"qmu-gpd", mtu3_qmu_gpd_show, }, 25562306a36Sopenharmony_ci}; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_cistatic int mtu3_ep_open(struct inode *inode, struct file *file) 25862306a36Sopenharmony_ci{ 25962306a36Sopenharmony_ci const char *file_name = file_dentry(file)->d_iname; 26062306a36Sopenharmony_ci const struct mtu3_file_map *f_map; 26162306a36Sopenharmony_ci int i; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mtu3_ep_files); i++) { 26462306a36Sopenharmony_ci f_map = &mtu3_ep_files[i]; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci if (strcmp(f_map->name, file_name) == 0) 26762306a36Sopenharmony_ci break; 26862306a36Sopenharmony_ci } 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci return single_open(file, f_map->show, inode->i_private); 27162306a36Sopenharmony_ci} 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_cistatic const struct file_operations mtu3_ep_fops = { 27462306a36Sopenharmony_ci .open = mtu3_ep_open, 27562306a36Sopenharmony_ci .read = seq_read, 27662306a36Sopenharmony_ci .llseek = seq_lseek, 27762306a36Sopenharmony_ci .release = single_release, 27862306a36Sopenharmony_ci}; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_cistatic const struct debugfs_reg32 mtu3_prb_regs[] = { 28162306a36Sopenharmony_ci dump_prb_reg("enable", U3D_SSUSB_PRB_CTRL0), 28262306a36Sopenharmony_ci dump_prb_reg("byte-sell", U3D_SSUSB_PRB_CTRL1), 28362306a36Sopenharmony_ci dump_prb_reg("byte-selh", U3D_SSUSB_PRB_CTRL2), 28462306a36Sopenharmony_ci dump_prb_reg("module-sel", U3D_SSUSB_PRB_CTRL3), 28562306a36Sopenharmony_ci dump_prb_reg("sw-out", U3D_SSUSB_PRB_CTRL4), 28662306a36Sopenharmony_ci dump_prb_reg("data", U3D_SSUSB_PRB_CTRL5), 28762306a36Sopenharmony_ci}; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_cistatic int mtu3_probe_show(struct seq_file *sf, void *unused) 29062306a36Sopenharmony_ci{ 29162306a36Sopenharmony_ci const char *file_name = file_dentry(sf->file)->d_iname; 29262306a36Sopenharmony_ci struct mtu3 *mtu = sf->private; 29362306a36Sopenharmony_ci const struct debugfs_reg32 *regs; 29462306a36Sopenharmony_ci int i; 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mtu3_prb_regs); i++) { 29762306a36Sopenharmony_ci regs = &mtu3_prb_regs[i]; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci if (strcmp(regs->name, file_name) == 0) 30062306a36Sopenharmony_ci break; 30162306a36Sopenharmony_ci } 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci seq_printf(sf, "0x%04x - 0x%08x\n", (u32)regs->offset, 30462306a36Sopenharmony_ci mtu3_readl(mtu->ippc_base, (u32)regs->offset)); 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci return 0; 30762306a36Sopenharmony_ci} 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_cistatic int mtu3_probe_open(struct inode *inode, struct file *file) 31062306a36Sopenharmony_ci{ 31162306a36Sopenharmony_ci return single_open(file, mtu3_probe_show, inode->i_private); 31262306a36Sopenharmony_ci} 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_cistatic ssize_t mtu3_probe_write(struct file *file, const char __user *ubuf, 31562306a36Sopenharmony_ci size_t count, loff_t *ppos) 31662306a36Sopenharmony_ci{ 31762306a36Sopenharmony_ci const char *file_name = file_dentry(file)->d_iname; 31862306a36Sopenharmony_ci struct seq_file *sf = file->private_data; 31962306a36Sopenharmony_ci struct mtu3 *mtu = sf->private; 32062306a36Sopenharmony_ci const struct debugfs_reg32 *regs; 32162306a36Sopenharmony_ci char buf[32]; 32262306a36Sopenharmony_ci u32 val; 32362306a36Sopenharmony_ci int i; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) 32662306a36Sopenharmony_ci return -EFAULT; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci if (kstrtou32(buf, 0, &val)) 32962306a36Sopenharmony_ci return -EINVAL; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mtu3_prb_regs); i++) { 33262306a36Sopenharmony_ci regs = &mtu3_prb_regs[i]; 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci if (strcmp(regs->name, file_name) == 0) 33562306a36Sopenharmony_ci break; 33662306a36Sopenharmony_ci } 33762306a36Sopenharmony_ci mtu3_writel(mtu->ippc_base, (u32)regs->offset, val); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci return count; 34062306a36Sopenharmony_ci} 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_cistatic const struct file_operations mtu3_probe_fops = { 34362306a36Sopenharmony_ci .open = mtu3_probe_open, 34462306a36Sopenharmony_ci .write = mtu3_probe_write, 34562306a36Sopenharmony_ci .read = seq_read, 34662306a36Sopenharmony_ci .llseek = seq_lseek, 34762306a36Sopenharmony_ci .release = single_release, 34862306a36Sopenharmony_ci}; 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_cistatic void mtu3_debugfs_create_prb_files(struct mtu3 *mtu) 35162306a36Sopenharmony_ci{ 35262306a36Sopenharmony_ci struct ssusb_mtk *ssusb = mtu->ssusb; 35362306a36Sopenharmony_ci const struct debugfs_reg32 *regs; 35462306a36Sopenharmony_ci struct dentry *dir_prb; 35562306a36Sopenharmony_ci int i; 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci dir_prb = debugfs_create_dir("probe", ssusb->dbgfs_root); 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mtu3_prb_regs); i++) { 36062306a36Sopenharmony_ci regs = &mtu3_prb_regs[i]; 36162306a36Sopenharmony_ci debugfs_create_file(regs->name, 0644, dir_prb, 36262306a36Sopenharmony_ci mtu, &mtu3_probe_fops); 36362306a36Sopenharmony_ci } 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci mtu3_debugfs_regset(mtu, mtu->ippc_base, mtu3_prb_regs, 36662306a36Sopenharmony_ci ARRAY_SIZE(mtu3_prb_regs), "regs", dir_prb); 36762306a36Sopenharmony_ci} 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_cistatic void mtu3_debugfs_create_ep_dir(struct mtu3_ep *mep, 37062306a36Sopenharmony_ci struct dentry *parent) 37162306a36Sopenharmony_ci{ 37262306a36Sopenharmony_ci const struct mtu3_file_map *files; 37362306a36Sopenharmony_ci struct dentry *dir_ep; 37462306a36Sopenharmony_ci int i; 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci dir_ep = debugfs_create_dir(mep->name, parent); 37762306a36Sopenharmony_ci mtu3_debugfs_ep_regset(mep->mtu, mep, dir_ep); 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mtu3_ep_files); i++) { 38062306a36Sopenharmony_ci files = &mtu3_ep_files[i]; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci debugfs_create_file(files->name, 0444, dir_ep, 38362306a36Sopenharmony_ci mep, &mtu3_ep_fops); 38462306a36Sopenharmony_ci } 38562306a36Sopenharmony_ci} 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_cistatic void mtu3_debugfs_create_ep_dirs(struct mtu3 *mtu) 38862306a36Sopenharmony_ci{ 38962306a36Sopenharmony_ci struct ssusb_mtk *ssusb = mtu->ssusb; 39062306a36Sopenharmony_ci struct dentry *dir_eps; 39162306a36Sopenharmony_ci int i; 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci dir_eps = debugfs_create_dir("eps", ssusb->dbgfs_root); 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci for (i = 1; i < mtu->num_eps; i++) { 39662306a36Sopenharmony_ci mtu3_debugfs_create_ep_dir(mtu->in_eps + i, dir_eps); 39762306a36Sopenharmony_ci mtu3_debugfs_create_ep_dir(mtu->out_eps + i, dir_eps); 39862306a36Sopenharmony_ci } 39962306a36Sopenharmony_ci} 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_civoid ssusb_dev_debugfs_init(struct ssusb_mtk *ssusb) 40262306a36Sopenharmony_ci{ 40362306a36Sopenharmony_ci struct mtu3 *mtu = ssusb->u3d; 40462306a36Sopenharmony_ci struct dentry *dir_regs; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci dir_regs = debugfs_create_dir("regs", ssusb->dbgfs_root); 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci mtu3_debugfs_regset(mtu, mtu->ippc_base, 40962306a36Sopenharmony_ci mtu3_ippc_regs, ARRAY_SIZE(mtu3_ippc_regs), 41062306a36Sopenharmony_ci "reg-ippc", dir_regs); 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci mtu3_debugfs_regset(mtu, mtu->mac_base, 41362306a36Sopenharmony_ci mtu3_dev_regs, ARRAY_SIZE(mtu3_dev_regs), 41462306a36Sopenharmony_ci "reg-dev", dir_regs); 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci mtu3_debugfs_regset(mtu, mtu->mac_base, 41762306a36Sopenharmony_ci mtu3_csr_regs, ARRAY_SIZE(mtu3_csr_regs), 41862306a36Sopenharmony_ci "reg-csr", dir_regs); 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci mtu3_debugfs_create_ep_dirs(mtu); 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci mtu3_debugfs_create_prb_files(mtu); 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci debugfs_create_file("link-state", 0444, ssusb->dbgfs_root, 42562306a36Sopenharmony_ci mtu, &mtu3_link_state_fops); 42662306a36Sopenharmony_ci debugfs_create_file("ep-used", 0444, ssusb->dbgfs_root, 42762306a36Sopenharmony_ci mtu, &mtu3_ep_used_fops); 42862306a36Sopenharmony_ci} 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_cistatic int ssusb_mode_show(struct seq_file *sf, void *unused) 43162306a36Sopenharmony_ci{ 43262306a36Sopenharmony_ci struct ssusb_mtk *ssusb = sf->private; 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci seq_printf(sf, "current mode: %s(%s drd)\n(echo device/host)\n", 43562306a36Sopenharmony_ci ssusb->is_host ? "host" : "device", 43662306a36Sopenharmony_ci ssusb->otg_switch.manual_drd_enabled ? "manual" : "auto"); 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci return 0; 43962306a36Sopenharmony_ci} 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_cistatic int ssusb_mode_open(struct inode *inode, struct file *file) 44262306a36Sopenharmony_ci{ 44362306a36Sopenharmony_ci return single_open(file, ssusb_mode_show, inode->i_private); 44462306a36Sopenharmony_ci} 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_cistatic ssize_t ssusb_mode_write(struct file *file, const char __user *ubuf, 44762306a36Sopenharmony_ci size_t count, loff_t *ppos) 44862306a36Sopenharmony_ci{ 44962306a36Sopenharmony_ci struct seq_file *sf = file->private_data; 45062306a36Sopenharmony_ci struct ssusb_mtk *ssusb = sf->private; 45162306a36Sopenharmony_ci char buf[16]; 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) 45462306a36Sopenharmony_ci return -EFAULT; 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci if (!strncmp(buf, "host", 4) && !ssusb->is_host) { 45762306a36Sopenharmony_ci ssusb_mode_switch(ssusb, 1); 45862306a36Sopenharmony_ci } else if (!strncmp(buf, "device", 6) && ssusb->is_host) { 45962306a36Sopenharmony_ci ssusb_mode_switch(ssusb, 0); 46062306a36Sopenharmony_ci } else { 46162306a36Sopenharmony_ci dev_err(ssusb->dev, "wrong or duplicated setting\n"); 46262306a36Sopenharmony_ci return -EINVAL; 46362306a36Sopenharmony_ci } 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci return count; 46662306a36Sopenharmony_ci} 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_cistatic const struct file_operations ssusb_mode_fops = { 46962306a36Sopenharmony_ci .open = ssusb_mode_open, 47062306a36Sopenharmony_ci .write = ssusb_mode_write, 47162306a36Sopenharmony_ci .read = seq_read, 47262306a36Sopenharmony_ci .llseek = seq_lseek, 47362306a36Sopenharmony_ci .release = single_release, 47462306a36Sopenharmony_ci}; 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_cistatic int ssusb_vbus_show(struct seq_file *sf, void *unused) 47762306a36Sopenharmony_ci{ 47862306a36Sopenharmony_ci struct ssusb_mtk *ssusb = sf->private; 47962306a36Sopenharmony_ci struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci seq_printf(sf, "vbus state: %s\n(echo on/off)\n", 48262306a36Sopenharmony_ci regulator_is_enabled(otg_sx->vbus) ? "on" : "off"); 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci return 0; 48562306a36Sopenharmony_ci} 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_cistatic int ssusb_vbus_open(struct inode *inode, struct file *file) 48862306a36Sopenharmony_ci{ 48962306a36Sopenharmony_ci return single_open(file, ssusb_vbus_show, inode->i_private); 49062306a36Sopenharmony_ci} 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_cistatic ssize_t ssusb_vbus_write(struct file *file, const char __user *ubuf, 49362306a36Sopenharmony_ci size_t count, loff_t *ppos) 49462306a36Sopenharmony_ci{ 49562306a36Sopenharmony_ci struct seq_file *sf = file->private_data; 49662306a36Sopenharmony_ci struct ssusb_mtk *ssusb = sf->private; 49762306a36Sopenharmony_ci struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; 49862306a36Sopenharmony_ci char buf[16]; 49962306a36Sopenharmony_ci bool enable; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) 50262306a36Sopenharmony_ci return -EFAULT; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci if (kstrtobool(buf, &enable)) { 50562306a36Sopenharmony_ci dev_err(ssusb->dev, "wrong setting\n"); 50662306a36Sopenharmony_ci return -EINVAL; 50762306a36Sopenharmony_ci } 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci ssusb_set_vbus(otg_sx, enable); 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci return count; 51262306a36Sopenharmony_ci} 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_cistatic const struct file_operations ssusb_vbus_fops = { 51562306a36Sopenharmony_ci .open = ssusb_vbus_open, 51662306a36Sopenharmony_ci .write = ssusb_vbus_write, 51762306a36Sopenharmony_ci .read = seq_read, 51862306a36Sopenharmony_ci .llseek = seq_lseek, 51962306a36Sopenharmony_ci .release = single_release, 52062306a36Sopenharmony_ci}; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_civoid ssusb_dr_debugfs_init(struct ssusb_mtk *ssusb) 52362306a36Sopenharmony_ci{ 52462306a36Sopenharmony_ci struct dentry *root = ssusb->dbgfs_root; 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci debugfs_create_file("mode", 0644, root, ssusb, &ssusb_mode_fops); 52762306a36Sopenharmony_ci debugfs_create_file("vbus", 0644, root, ssusb, &ssusb_vbus_fops); 52862306a36Sopenharmony_ci} 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_civoid ssusb_debugfs_create_root(struct ssusb_mtk *ssusb) 53162306a36Sopenharmony_ci{ 53262306a36Sopenharmony_ci ssusb->dbgfs_root = 53362306a36Sopenharmony_ci debugfs_create_dir(dev_name(ssusb->dev), usb_debug_root); 53462306a36Sopenharmony_ci} 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_civoid ssusb_debugfs_remove_root(struct ssusb_mtk *ssusb) 53762306a36Sopenharmony_ci{ 53862306a36Sopenharmony_ci debugfs_remove_recursive(ssusb->dbgfs_root); 53962306a36Sopenharmony_ci ssusb->dbgfs_root = NULL; 54062306a36Sopenharmony_ci} 541