Files
android/drivers/usb/mtu3/mtu3_debugfs_v2.c
T
threeeye bc1d038eac REVVL 6 Pro kernel bring-up: full working tree snapshot (2026-09-12)
Squashed backup commit (no shallow-clone history issues) of
xiaomi-mt6833-dev/kernel_xiaomi_mt6833 (lineage-23.2 branch, upstream
commit 9eece662e) plus all fixes applied to get everpal_defconfig building
clean against a modern (GCC 15.2.0) toolchain -- see the previous commit
message on the lineage-23.2 branch (also in this repo history is not
available here since this is a squashed snapshot; full incremental history
lives in the local DL380 checkout and the upstream GitHub remote).

Upstream: https://github.com/xiaomi-mt6833-dev/kernel_xiaomi_mt6833 (lineage-23.2)
2026-09-12 13:36:46 +00:00

311 lines
7.2 KiB
C

/*
* mtu3_gadget.c - MediaTek usb3 DRD peripheral support
*
* Copyright (C) 2016 MediaTek Inc.
*
* Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h>
#include <linux/platform_device.h>
#include "mtu3.h"
#include "mtu3_hal.h"
#include "mtu3_dr.h"
#define PROC_DIR_MTK_USB "mtk_usb"
#define PROC_FILE_SMTERRCOUNT "mtk_usb/smt_err_count"
#define PROC_FILE_IPPCREG "mtk_usb/ippc_reg"
#define PROC_FILE_MACREG "mtk_usb/mac_reg"
#define PROC_FILE_SPEED "mtk_usb/speed"
#define PROC_FILE_NUM 4
static struct proc_dir_entry *proc_files[PROC_FILE_NUM] = {
NULL, NULL, NULL, NULL};
static u32 mac_value, mac_addr;
static u32 ippc_value, ippc_addr;
static int smt_err_count_get(void *data, u64 *val)
{
struct ssusb_mtk *ssusb = NULL;
if (IS_ERR_OR_NULL(data))
return -EFAULT;
ssusb = data;
*val = ssusb_u3loop_back_test(ssusb);
mtu3_printk(K_INFO, "%s %llu\n", __func__, *val);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(smt_err_count, smt_err_count_get, NULL, "%llu\n");
static void mac_write32(struct ssusb_mtk *ssusb, int offset,
int mask, int val)
{
u32 cur_value;
u32 new_value;
struct resource *res;
struct mtu3 *mtu = ssusb->u3d;
struct platform_device *pdev = to_platform_device(ssusb->dev);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mac");
if (IS_ERR_OR_NULL(res) || offset >= resource_size(res)) {
pr_info("%s error range\n", __func__);
return;
}
cur_value = mtu3_readl(mtu->mac_base, offset);
new_value = (cur_value & (~mask)) | val;
mtu3_writel(mtu->mac_base, offset, new_value);
}
static void ippc_write32(struct ssusb_mtk *ssusb, int offset,
int mask, int val)
{
u32 cur_value;
u32 new_value;
struct resource *res;
struct mtu3 *mtu = ssusb->u3d;
struct platform_device *pdev = to_platform_device(ssusb->dev);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ippc");
if (IS_ERR_OR_NULL(res) || offset >= resource_size(res)) {
pr_info("%s error range\n", __func__);
return;
}
cur_value = mtu3_readl(mtu->ippc_base, offset);
new_value = (cur_value & (~mask)) | val;
mtu3_writel(mtu->ippc_base, offset, new_value);
}
static int mac_rw_show(struct seq_file *s, void *unused)
{
seq_printf(s, "MAC: [0x%x] = 0x%x\n", mac_addr, mac_value);
return 0;
}
static ssize_t mac_rw_write(struct file *file,
const char __user *ubuf, size_t count, loff_t *ppos)
{
struct seq_file *s = file->private_data;
struct ssusb_mtk *ssusb = s->private;
struct mtu3 *mtu = ssusb->u3d;
char buf[40];
memset(buf, 0x00, sizeof(buf));
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
return -EFAULT;
if (!strncmp(buf, "w", 1)) {
u32 offset;
u32 value;
u32 shift;
u32 mask;
if (sscanf(buf, "w32 0x%x:%d:0x%x:0x%x",
&offset, &shift, &mask, &value) == 4) {
if ((offset % 4) != 0) {
pr_notice("Must use 32bits alignment address\n");
return count;
}
mac_write32(ssusb, offset,
mask << shift, value << shift);
} else
return -EFAULT;
}
if (!strncmp(buf, "r", 1)) {
u32 offset;
if (sscanf(buf, "r32 0x%x", &offset) == 1) {
if ((offset % 4) != 0) {
pr_notice("Must use 32bits alignment address\n");
return count;
}
mac_addr = offset;
mac_value = mtu3_readl(mtu->mac_base, offset);
}
}
return count;
}
static int mac_rw_open(struct inode *inode, struct file *file)
{
return single_open(file, mac_rw_show, PDE_DATA(inode));
}
static const struct file_operations mac_rw_fops = {
.open = mac_rw_open,
.write = mac_rw_write,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int ippc_rw_show(struct seq_file *s, void *unused)
{
seq_printf(s, "IPPC: [0x%x] = 0x%x\n", ippc_addr, ippc_value);
return 0;
}
static ssize_t ippc_rw_write(struct file *file,
const char __user *ubuf, size_t count, loff_t *ppos)
{
struct seq_file *s = file->private_data;
struct ssusb_mtk *ssusb = s->private;
struct mtu3 *mtu = ssusb->u3d;
char buf[40];
memset(buf, 0x00, sizeof(buf));
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
return -EFAULT;
if (!strncmp(buf, "w", 1)) {
u32 offset;
u32 value;
u32 shift;
u32 mask;
if (sscanf(buf, "w32 0x%x:%d:0x%x:0x%x",
&offset, &shift, &mask, &value) == 4) {
if ((offset % 4) != 0) {
pr_notice("Must use 32bits alignment address\n");
return count;
}
ippc_write32(ssusb, offset,
mask << shift, value << shift);
} else
return -EFAULT;
}
if (!strncmp(buf, "r", 1)) {
u32 offset;
if (sscanf(buf, "r32 0x%x", &offset) == 1) {
if ((offset % 4) != 0) {
pr_notice("Must use 32bits alignment address\n");
return count;
}
ippc_addr = offset;
ippc_value = mtu3_readl(mtu->ippc_base, offset);
}
}
return count;
}
static int ippc_rw_open(struct inode *inode, struct file *file)
{
return single_open(file, ippc_rw_show, PDE_DATA(inode));
}
static const struct file_operations ippc_rw_fops = {
.open = ippc_rw_open,
.write = ippc_rw_write,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int mtu3_speed_show(struct seq_file *s, void *unused)
{
seq_printf(s, "mtu3_speed = %d\n", mtu3_speed);
return 0;
}
static int mtu3_speed_open(struct inode *inode, struct file *file)
{
return single_open(file, mtu3_speed_show, PDE_DATA(inode));
}
static ssize_t mtu3_speed_write(struct file *file,
const char __user *ubuf, size_t count, loff_t *ppos)
{
char buf[20];
int val;
memset(buf, 0x00, sizeof(buf));
if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
return -EFAULT;
if (kstrtouint(buf, 10, &val) == 0 && val >= 0 && val <= 1)
mtu3_speed = val;
else
return -EINVAL;
return count;
}
static const struct file_operations mtu3_speed_fops = {
.open = mtu3_speed_open,
.write = mtu3_speed_write,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
void ssusb_debugfs_init(struct ssusb_mtk *ssusb)
{
int idx = 0;
proc_mkdir(PROC_DIR_MTK_USB, NULL);
if (ssusb->u3_loopb_support) {
proc_files[idx] = proc_create_data(PROC_FILE_SMTERRCOUNT, 0644, NULL,
&smt_err_count, ssusb);
if (!proc_files[idx])
dev_dbg(ssusb->dev, "file smt_err_count failed\n");
idx++;
}
proc_files[idx] = proc_create_data(PROC_FILE_IPPCREG, 0644, NULL,
&ippc_rw_fops, ssusb);
if (!proc_files[idx])
dev_dbg(ssusb->dev, "file ippc_reg failed\n");
idx++;
proc_files[idx] = proc_create_data(PROC_FILE_MACREG, 0644, NULL,
&mac_rw_fops, ssusb);
if (!proc_files[idx])
dev_dbg(ssusb->dev, "file mac_reg failed\n");
idx++;
proc_files[idx] = proc_create_data(PROC_FILE_SPEED, 0644, NULL,
&mtu3_speed_fops, ssusb);
if (!proc_files[idx])
dev_dbg(ssusb->dev, "file speed failed\n");
}
void ssusb_debugfs_exit(struct ssusb_mtk *ssusb)
{
int idx = 0;
for (; idx < PROC_FILE_NUM ; idx++) {
if (proc_files[idx])
proc_remove(proc_files[idx]);
}
}