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