RK3588 kernel-6.1 drivers/usb/roles 代码功能与实现原理
1. 目录与产物
路径:rk3588/kernel-6.1/drivers/usb/roles/。
| 文件 | Makefile 目标 |
作用 |
|---|---|---|
class.c |
roles.o(CONFIG_USB_ROLE_SWITCH,模块名 roles.ko) |
USB Role Switch 框架:注册 usb_role class、usb_role_switch_register、sysfs、lookup API |
intel-xhci-usb-role-switch.c |
CONFIG_USB_ROLES_INTEL_XHCI(依赖 ACPI + X86) |
Intel Atom 等平台:MMIO DUAL_ROLE_CFG* 切换 xHCI ↔ dwc3 gadget |
公开 API 声明:include/linux/usb/role.h。
2. 要解决什么问题(Kconfig 语义)
同一 Type‑C / OTG 物理口可能:
- 内部是一个 DRD 控制器(如 DWC3):控制器驱动内部切换 Host/Device;仍可通过
usb_role_switch统一 对外接口 / sysfs / DT connection。 - Host 与 Device 是两颗独立控制器,中间经 MUX 连到连接器:需要 软件选定 数据通路接到哪一侧。
Role Switch 抽象的就是:把「当前口是 Host 还是 Device」变成可查询、可设置的内核对象,供 Type‑C(TCPM/extcon)、PMIC、电源策略 与 USB 控制器 probe 协作。
3. 核心对象:struct usb_role_switch(class.c)
内部字段要点:
enum usb_role role:USB_ROLE_NONE/HOST/DEVICEset(sw, role):必选,由 注册方(SoC glue、MUX 驱动等)实现 写硬件/ACPIget(sw):可选;缺省时usb_role_switch_get_role返回 缓存的sw->role(上次set成功值)mutex lock:串行化 set/getregistered:unregister 后set_role返回-EOPNOTSUPPallow_userspace_control:为真时sysfs role可写(见下文)
可选 usb2_port / usb3_port / udc:文档说明用于指向 主机口设备与 UDC,便于后续 symlink(代码里仍有 TODO)。
4. 注册与 sysfs
usb_role_switch_register(parent, desc):
- 创建子设备,名
{name}-role-switch(默认{parent_name}-role-switch) class:usb_roledevice_type:usb_role_switch
属性 role:
- 读:
none/host/device(usb_role_string) - 写:仅在
allow_userspace_control时可见(is_visible);写入经sysfs_match_string解析后调用usb_role_switch_set_role set_role成功后kobject_uevent(KOBJ_CHANGE),便于 udev
usb_role_switch_uevent:导出环境变量 USB_ROLE_SWITCH= 设备名。
5. 查找与模块引用
usb_role_switch_get(dev)- 若
dev的父 fwnode 带usb-role-switch属性 → 按 父节点 找 switch - 否则
device_connection_find_match(dev, "usb-role-switch", …)
- 若
fwnode_usb_role_switch_get:DT graph / connection 等价路径usb_role_switch_find_by_fwnode:按 switch 自身 fwnode 查找
找到后对 sw->module try_module_get,put 时 module_put。
原理:DWC2 dual-role、DWC3 drd.c、Type‑C 等通过 DT usb-role-switch 连接拿到 struct usb_role_switch *,在 线缆插入、TCPM 决策 时调用 usb_role_switch_set_role,与 dwc3_set_mode、phy_set_mode 等衔接。
6. Intel 参考驱动:intel-xhci-usb-role-switch.c
平台:Cherry Trail / Broxton 等 ACPI platform_device,MMIO 寄存器 DUAL_ROLE_CFG0/1:
intel_xhci_usb_set_role:按角色写SW_IDPIN、SW_VBUS_VALID、DRD_CONFIG_*、SW_SWITCH_EN;与 ACPI global lock 互斥(避免与 AML 竞争);轮询 CFG1 HOST_MODE 确认切换完成intel_xhci_usb_get_role:读 CFG0 推导 Host/Device/NONE
通过 software_node 提供 fwnode,便于 connection 与其它驱动匹配;allow_userspace_control = true。
RK3588:一般 不走该 Intel 驱动;角色切换多在 dwc3 + typec/extcon 路径完成,但若 DTS 引用 usb-role-switch,仍会用到 roles.ko 框架 API。
7. 与其它目录的关系(概念)
1 | TCPM / extcon / PMIC(策略) |
8. 延伸阅读(本仓库)
| 文档 |
|---|
| drivers-usb-typec分析.md |
| drivers-usb-dwc3详细分析.md |
内核文档可参考:Documentation/driver-api/usb/usb-role-switch.rst(若树中存在)。
基于 rk3588/kernel-6.1/drivers/usb/roles 与 include/linux/usb/role.h 归纳。
正在加载留言…