MT6575 USB驱动源码解析:从MUSB到OTG切换与枚举排错实战
2026/9/16 3:21:24 网站建设 项目流程

简介:MT6575平台USB驱动源码包,面向嵌入式工程师及MTK平台驱动开发人员,适合需要深入理解USB协议、进行驱动移植或调试的开发者。压缩包共42个文件,包括21个头文件与20个C源文件,另附1个说明文本,整体仅153KB,轻量精炼。源码覆盖主机端与设备端USB驱动,围绕枚举过程、配置与接口选择、端点管理、数据传输、中断与同步传输、电源管理以及故障恢复等核心环节展开,并具体提供主机海量存储、虚拟串口、视频传输、OTG等模块实现,可直观对照联发科平台USB架构。例如,主机侧海量存储适配、虚拟串口通信、视频传输以及主从切换逻辑等典型场景都有对应代码可直接研读。目前已有159人学习该资源,对研究MT6575平台或同类MTK方案的开发者而言,这份源码既能用于协议原理分析,也能作为新硬件驱动的定制起点,实用价值明显。

1. 拿到 usb.rar 后先分清 MT6575 USB 源码的边界

做 MT6575 平台系统移植的工程师,几乎都会在某个阶段打开一个名叫 usb.rar 的压缩包。它通常来自 MediaTek BSP 内核源码旁的一个独立归档,装的是这颗 Cortex-A9 双核 SoC 的 USB 驱动源码:Linux 3.0/3.4 内核下的 MUSB 控制器驱动、MediaTek 的 otg 与 phy 适配、以及 Android gadget 侧 adb 和 mtp 的注册逻辑。别把它当成完整协议栈来看,它只负责把硬件控制器变成内核能认的 device 或 host 接口。

这套代码实际只覆盖三件事:设备模式下 adb 能不能成功枚举,host 模式下 OTG 口能不能识别 U 盘与键鼠,以及充电场景里 vbus 与 ID 引脚的状态切换干不干净。任何一条出问题,表象都是“USB 连不上”,但排查入口完全不同。下面按源码目录分层、probe 注册流程、usb 抓包验证的顺序展开,适合做内核裁剪、USB 驱动移植,以及被“插上没反应”反复折腾的 BSP 工程师;读完你会知道先开哪些文件、核对哪些参数、用什么手段验证枚举结果。

2. MT6575 USB 驱动源码目录分层:从 MUSB core 到 mtk otg

2.1 解包并圈定内核里的 USB 相关目录

拿到 usb.rar 之后,第一件事不是解完就全局搜索,而是先建立目录地图。常见做法是把包解到内核源码树平级的地方,然后按路径筛选:

mkdir -p ~/mtk6575_bsp && cd ~/mtk6575_bsp unrar x ../usb.rar find . -maxdepth 4 -type d \( -iname "*usb*" -o -iname "*otg*" \) | sort

这段命令里-maxdepth 4是关键。MT6575 的 BSP 目录层级很深,直接 find 会扫出大量编译产物和中间目录,拖慢定位速度;-iname同时匹配大小写,usb、USB、Usb 都不会漏。运行后通常会出现三类命中:kernel/drivers/usb 下的 musb 与 gadget,arch/arm/mach-mt6575 下的板级描述,以及 drivers/misc/mediatek 里以 usb20 或 usb_phy 命名的硬件适配目录。

MT6575 的 USB 控制器是 Mentor MUSB 这一系的 USB 2.0 High-Speed OTG 核,内核侧主体在 drivers/usb/musb:musb_core 负责寄存器操作与端点调度,SoC 差异落在 glue 平台适配里。MediaTek 在 musb 之外还单独维护了 otg 状态逻辑和 PHY 初始化代码,后者常放在 mach-mt6575 或 misc/mediatek 下,而不在标准 musb 目录里。所以全局搜musb只会看到一半真相,另一半要搜mtk_usbusb20这类 MediaTek 自己的符号。

2.2 MUSB core、glue、PHY、otg 各管哪一段

把 USB 驱动拆成四层之后,排错时才清楚去哪一层找日志。MUSB core 管端点调度、寄存器读写和中断处理,它不关心引脚定义;glue 层把 musb 的通用接口接到 MT6575 的平台资源上,包括时钟、复位和 gadget 注册;PHY 层处理 D+/D- 收发器配置与 HS 握手;otg 层则靠 ID 引脚和 vbus 检测决定控制器跑 host 还是 device。

这四层不是四个文件,而是一组文件的组合。下表是旧 BSP 里常用的定位对应关系,不同版本文件名略有出入,但职责划分基本一致:

代码职责常见路径特征排查时关注点
MUSB corekernel/drivers/usb/musb/musb_core.c端点注册、中断状态
平台 gluearch/arm/mach-mt6575 下 usb 相关文件时钟、复位、platform_data
PHY 适配drivers/misc/mediatek/usb20 或 usb_phyHS 握手、眼图、降速
OTG 状态机文件名含 otg 的 .c 文件ID 电平、vbus 检测来源
gadget 配置kernel/drivers/usb/gadget/android.cadb/mtp 是否注册

排错时最常见的错误是只盯 musb_core 的打印。MT6575 上“插上没反应”的根因多半在 glue 或 otg 层:时钟没开、ID 引脚配错、vbus 走 PMIC 中断而驱动没订阅。先按这张表判断问题属于哪一层,再决定要不要上 usb 抓包,能省掉一大半无效调试。

2.3 用 Source Insight 4.0 建工程时该勾哪些目录

这份源码的读法也和普通内核源码不同。直接用 Source Insight 4.0 打开整个 kernel 树,会陷进几百个无关 driver 和编译产物里,跳转查函数极慢。常见做法是新建一个专用工程,只加入三块:kernel/drivers/usb、arch/arm/mach-mt6575、kernel/include/linux/usb。mach-mt6575 体积大但必须加,因为 usb 的 platform_data、GPIO 默认配置和寄存器基址宏都在这里,漏掉它,所有符号跳转都会断在半路。

工程建好后先全局搜mtk_usbusb20。旧平台的平台驱动常用这两个名字命名入口,命中后右键跳到定义处,顺着 probe 函数开始读。Source Insight 4.0 的 symbol window 会把 musb、gadget、otg 的函数分屏列出,适合在四个职责层之间来回跳转对比调用顺序,比用单文件 grep 效率高很多。

提示:如果压缩包里带版本号目录(如 usb_1.0、usb_1.1),优先读版本号高的那份,低版本通常是发布前归档,容易误导。

3. MT6575 usb 驱动 probe 流程与 otg 切换的三个核对点

3.1 从 mtk_usb 的 probe 函数读注册顺序

拿到驱动先读 probe,但不要逐行读。MT6575 平台的 usb probe 通常按固定顺序处理五件事:取寄存器资源、读 ID 与 vbus 引脚配置、初始化 PHY、启动控制器、注册 UDC。任何一步静默失败,后续功能都起不来。简化后的骨架在旧平台上大致如此:

/* 示意代码:MT6575 usb 平台驱动 probe 通用骨架 */ static int mtk_usb_probe(struct platform_device *pdev) { struct resource *res; /* 1. 寄存器基址来自板级文件或 dts,老 BSP 多用 platform_data */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENXIO; mtk_usb_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); /* 2. ID 引脚挂在 mtk gpio 控制器下,决定 host/device 方向 */ mtk_usb_otg_init(pdev); /* 3. PHY 上电复位,失败直接返回,USB 起不来 */ if (mtk_usb_phy_init(mtk_usb_base) < 0) return -EIO; /* 4. 注册 UDC,供 android_usb 复合 gadget 挂 adb/mtp */ return usb_add_gadget_udc(&pdev->dev, &mtk_udc); }

三个细节值得注意。第一,devm_ioremap失败时要保留真实错误码,很多人随手改成-1,上层就没法区分映射失败和 PHY 初始化失败。第二,otg 初始化要排在 PHY 之前,因为 ID 引脚的电平采样依赖 gpio 控制器时钟,而那个时钟挂在 otg 模块下面,顺序反了会一直读到固定电平,表现为 OTG 永远切不到 host。第三,usb_add_gadget_udc只在 device 侧注册,host 侧走同一控制器的 host 通道,不会产生第二个平台设备。

3.2 ID 引脚与 vbus 检测:otg 切换的判定来源

MT6575 的 otg 切换不靠软件轮询,而是两个硬件信号:ID 引脚和 vbus。ID 为低说明插的是 device 线缆,控制器进 device 模式;ID 为高且 vbus 有电表示外接了 U 盘或键鼠,切 host;两者都不满足时保持空闲。

实际排错中问题常出在 ID 引脚对应的 mtk gpio 配置上。老 BSP 里这一项写在板级文件的 platform_data 中,而不是设备树。需要确认三件事:该 GPIO 是否被其他模块复用、是否配置为输入且带内部上拉、otg 驱动读取的编号和硬件实际连接是否一致。复用冲突的典型症状是 ID 电平随机跳变,dmesg 里出现频繁的 host/device 反复切换,每次切换伴随一次总线复位,插上的设备自然无法稳定枚举。

vbus 检测则要分清来源。MT6575 的 vbus 通常由 PMIC 充电器检测中断通知,USB 驱动订阅的是 notifier 回调,而不是直接读 GPIO。如果源码里找不到 vbus 采样点,去 mtk 的 charger 或 pmic 目录搜vbus回调关键字,答案大概率在那里。很多移植者以为少了 USB 驱动里的某行读 GPIO 代码,实际是 PMIC 那边没使能中断上报。

3.3 三个必调的配置项与 usb 协议约束

以下参数在 MT6575 USB 源码里出现的频率最高,改动前先对照:

参数/宏常见位置影响
CONFIG_USB_MTK_OTGkernel defconfig编译 otg 状态机,不选则只剩 device
CONFIG_USB_ANDROIDdrivers/usb/gadget/Kconfigadb/mtp 复合设备注册
id-gpios / usb_idboard 文件或 dtsOTG 方向判定
时钟 gate 配置mach-mt6575 时钟文件控制器寄存器读写

以 CONFIG_USB_MTK_OTG 为例,默认 defconfig 没开时,系统只有 device 模式,插 U 盘完全无反应,而 dmesg 里没有一条报错,这是最容易误判的一类。时钟 gate 配置错了,表现是读写控制器寄存器直接超时或总线 hang,抓包层面看不到任何数据,先于协议层问题排掉。

还有一条 usb 协议硬约束:设备枚举时 D+ 上拉由 PHY 内部完成,HS 握手成功后 bMaxPacketSize0 必须是 64。如果 PHY 的 host_disconnect 检测与 device 上拉切换不同步,usb 抓包里会看到 host 反复发 SETUP 而没有 ACK,设备侧却认为自己的工作完全正常。

4. 用 usb 抓包和 dmesg 定位 MT6575 枚举失败的套路

4.1 先分清是驱动层问题还是协议层问题

枚举失败的排错有个固定顺序:先确认驱动有没有起来,再看协议层有没有应答。驱动层看 dmesg,协议层看 usb 抓包,混在一起查最浪费时间。驱动层检查用下面的命令:

adb shell "echo 8 > /proc/sys/kernel/printk" adb shell dmesg | grep -iE "musb|mtk_usb|otg|vbus"

打开 printk 级别是为了把 dev_dbg 层级以下的日志也放进 dmesg 环形缓冲,否则驱动里大量调试打印不会输出。adb 本身连不上时,就把串口线接到板子 UART 调试口,从 console 过滤同样的关键字。MT6575 的 usb 驱动和 otg 状态机各自带打印开关,常见形式是 module_param 控制的 debug 级别。

驱动层正常时,dmesg 应能按顺序看到 PHY init 完成、UDC 注册成功、otg 进入对应状态三个标记;缺任何一步都不用抓包,回去查驱动本身。常见反例是只看到 PHY init 就断了,后面 otg 状态机的日志消失,这时候问题几乎都在平台资源或 gpio 申请失败上。

4.2 用 usbmon 抓包:枚举过程的协议层证据

usb 抓包不一定要买硬件。Linux 主机侧用 usbmon 把总线上的 URB 流转发抓下来,再用 Wireshark 分析。前提是 MT6575 以 device 模式连到 PC,或者 PC 上接入 MT6575 host 口控制的设备。抓包命令:

sudo modprobe usbmon ls /sys/kernel/debug/usb/usbmon/ sudo cat /sys/kernel/debug/usb/usbmon/1u > mt6575_usb.pcap # 插入设备,枚举结束后 Ctrl+C 停止,Wireshark 打开 pcap

1u里的 1 是总线编号,PC 有多个主机控制器时用lsusb确认目标设备在几号总线;u表示抓 URB 流转发版本,会保留数据传输内容,比默认的1t更适合分析枚举阶段。抓到后先用过滤器usb.setup只看控制传输,枚举阶段绝大多数包都是 SETUP。

接着需要一点 usb 协议知识:枚举是 host 主导的,host 发 GET_DESCRIPTOR,设备回 DESC 或 STALL。MT6575 设备模式下两种异常最常见:一是 SETUP 发出后总线完全无响应,说明设备侧控制器或 PHY 没起来,回驱动层查;二是 descriptor 里 bMaxPacketSize0 与控制器配置不符,host 会连续重试然后放弃,这类问题要回 PHY 查 HS 握手,和 gadget 配置没有关系。

4.3 三类高频故障的判据

综合 dmesg 和抓包结果,MT6575 上反复出现的 USB 问题可以归成三类:

故障现象dmesg/抓包特征优先排查方向
OTG 插 U 盘无反应无 a_bus_req 或 a_host 状态记录ID 引脚 gpio、vbus 回调
adb 枚举为未知设备GET_DESCRIPTOR 无应答PHY 复位、时钟 gate、D+ 上拉
host 反复断开重连disconnect/connect 循环ID 抖动、D+/D- 线质量

D+/D- 数据线质量问题是老平台特有的坑。现象是 HS 握手时好时坏,usb 抓包能看到 chirp 序列不完整,有时直接掉到 FS 速率。不用一上来怀疑驱动,先量 D+/D- 的对地阻抗和走线串阻;MT6575 参考设计要求在 SoC 侧串联 22Ω 电阻,BSP 移植时把这两颗电阻省掉或换阻值,枚举稳定性立刻变差。

提示:usbmon 只能从 PC 侧抓包,抓不到 MT6575 作为 host 时自己发出的包。想验证 host 侧枚举,可以在板上挂一个 USB 协议分析仪,或用串口把 musb 的中断状态打印拉开,观察总线活动。

5. 从源码到复现:MT6575 USB 的 30 分钟排查路径

前 10 分钟解包建工程。解压 usb.rar 后,用 Source Insight 4.0 只加载 kernel/drivers/usb、arch/arm/mach-mt6575、kernel/include/linux/usb 三个目录,搜索mtk_usb跳到 probe 函数,确认 PHY init、otg init、UDC 注册三个步骤的返回值和日志位置。没有 Source Insight 也可以用 ctags,但面对 mach 目录下大量宏定义时,交互式跳转会舒服得多。

中间 10 分钟做驱动层判定。插上目标设备后在板端跑:

for d in /sys/bus/usb/devices/*/; do [ -f "$d/idVendor" ] && \ echo "$d $(cat $d/idVendor):$(cat $d/idProduct) speed=$(cat $d/speed)" done

这个循环比 lsusb 更贴近内核视图。枚举成功时每个设备目录都有 idVendor、idProduct、speed 三个文件;speed 显示 480 表示 HS 握手成功,12 表示降到 FS,文件不存在表示设备目录都没创建,问题在更底层。设备目录存在但 speed 是 12 时,优先查 PHY 的 HS 握手,而不是 gadget 配置。

最后 10 分钟留给协议层。在 PC host 侧用 usbmon 抓包,过滤usb.setup检查 GET_DESCRIPTOR 应答:有响应且包长正确,说明驱动与协议层都正常;无响应回到 dmesg;响应内容乱码就去量 D+/D- 硬件。每次改完驱动,都先跑 sysfs 脚本记录三行结果,再决定要不要抓包,别一上来就把抓包当成默认动作,否则文件越攒越多,有效信息被淹没。把 idVendor、idProduct 和 speed 三条记录直接 tee 到一个比对文件,前后两次改动对照,几分钟就能看清枚举行为是否被这次改动影响。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询