仅从你贴的 dwc2_driver_probe() 来看:
不能简单地说 OTG 模式默认初始化为 Gadget(Device) 模式。
需要看 dr_mode 和 OTG 检测结果。
先看这段代码
retval = dwc2_get_dr_mode(hsotg);
这里会读取设备树:
dr_mode = "host";
dr_mode = "peripheral";
dr_mode = "otg";
然后设置:
hsotg->dr_mode
如果 dr_mode=peripheral
会执行:
dwc2_gadget_init(hsotg);
不会执行:
dwc2_hcd_init(hsotg);
因为:
if (hsotg->dr_mode != USB_DR_MODE_PERIPHERAL)
dwc2_hcd_init(hsotg);
条件不成立。
最终就是:
纯Device模式
如果 dr_mode=host
会执行:
dwc2_hcd_init(hsotg);
不会执行:
dwc2_gadget_init(hsotg);
因为:
if (hsotg->dr_mode != USB_DR_MODE_HOST)
dwc2_gadget_init(hsotg);
条件不成立。
最终:
纯Host模式
如果 dr_mode=otg
你的情况应该是这个。
此时:
if (hsotg->dr_mode != USB_DR_MODE_HOST)
dwc2_gadget_init(hsotg);
if (hsotg->dr_mode != USB_DR_MODE_PERIPHERAL)
dwc2_hcd_init(hsotg);
两个条件都成立。
因此:
probe阶段:
Gadget初始化
HCD初始化
都会执行。
为什么两个都初始化?
因为 OTG 需要支持动态切换:
Host <----> Device
Linux 必须提前准备:
Gadget Framework
Host Controller Driver
OTG状态机
所以:
probe
├─ dwc2_gadget_init()
├─ dwc2_hcd_init()
└─ dwc2_drd_init()
都会执行。
那最终是 Host 还是 Device?
这取决于 OTG 检测。
例如 Micro-USB OTG:
ID脚
ID = 0
Host
ID = 1
Device
或者 Type-C:
CC逻辑
↓
Role Switch
从代码看
最关键的是:
retval = dwc2_drd_init(hsotg);
DRD = Dual Role Device。
这里会建立:
OTG FSM
Role Switch
Extcon
USB Role Switch
等机制。
后面根据:
ID
VBUS
Type-C事件
决定当前角色。
再看你之前贴的代码
if (dwc2_is_device_mode(hsotg)) {
spin_unlock_irqrestore(&hsotg->lock, flags);
return 0;
}
这是 _dwc2_hcd_start()。
说明:
虽然HCD已经初始化了
但当前角色是Device
于是:
不启动Host
不打开VBUS
直接返回
因此 OTG 模式下实际流程通常是
probe
├─ dwc2_gadget_init()
├─ dwc2_hcd_init()
└─ dwc2_drd_init()
当前无连接
↓
默认Device状态(很多平台如此)
插入OTG Host线(ID=0)
↓
切换Host
↓
_dwc2_hcd_start()
↓
dwc2_vbus_supply_init()
↓
regulator_enable()
拔线
↓
切回Device
↓
dwc2_hcd_stop()
↓
regulator_disable()
所以针对你的代码:
OTG 模式下并不是“只初始化 Gadget”。
而是:
-
dwc2_gadget_init()会执行; -
dwc2_hcd_init()也会执行; -
真正运行成 Host 还是 Device,要等
dwc2_drd_init()建立的 OTG/Role-Switch 机制根据 ID、VBUS 或 Type-C 事件来决定。
不过在很多 SoC(包括不少 STM32、Rockchip、TI 平台)的 OTG 场景下,上电后的初始角色往往是 Device(B-device),所以你会看到 _dwc2_hcd_start() 里经常首先判断:
dwc2_is_device_mode(hsotg)
成立后直接返回。这样 Host 部分虽然初始化过,但并未真正启动,也不会打开 VBUS。

1740

被折叠的 条评论
为什么被折叠?



