rk3588 偶现usb无法使用

目录

背景介绍

分析过程

日志分析

追踪代码

原因分析

1. 检查函数传参以及代码流程

2. 检查调用逻辑

3. 增加延时

4. 配置成usb3.0

打开usbdp相关的phy

删除maximum-speed

删除usbdrd_dwc3_0中phy的配置

总结


背景介绍

rk3588有5个usb控制器,Type-C0/1接口可以简化成usb接口,作者项目中就是Type-C0作为usb2.0 only使用。
按照rk3588 usb开发参考文档进行配置
《Rockchip_RK3588_Developer_Guide_USB_CN.pdf》
        Type-C USB 2.0 only DTS配置
                配置3.硬件电路不带外置Type-C控制芯片,支持OTG

&usbdrd3_0 {
	status = "okay";
};

&usbdrd_dwc3_0 {
	status = "okay";
	dr_mode = "otg";
    phys = <&u2phy0_otg>;
    phy-names = "usb2-phy";
    maximum-speed = "high-speed";
    extcon = <&u2phy0>;
};

&u2phy0 {
	status = "okay";
};

&u2phy0_otg {
	status = "okay";
};
&usbdp_phy0 {
	status = "disabled";
};

&usbdp_phy0_dp {
	status = "disabled";
};

&usbdp_phy0_u3 {
	status = "disabled";
};

发现偶现usb不可用,概率大约20%

分析过程

日志分析

通过串口log对比正常和异常log,找到usb相关差异

异常log会有如下报错
dwc3 fc000000.usb: failed to enable ep0out
正常log没有报错,会有
dwc3 fc000000.usb: device reset

追踪代码

找到对应代码位置

driver/usb/dwc3/gadget.c
__dwc3_gadget_start()
{
........
	dep = dwc->eps[0];
	ret = __dwc3_gadget_ep_enable(dep, DWC3_DEPCFG_ACTION_INIT);
	if (ret) {
		dev_err(dwc->dev, "failed to enable %s\n", dep->name);
		goto err0;
	}
........
}

添加log,找到最初报错位置

driver/usb/dwc3/gadget.c
dwc3_send_gadget_ep_cmd()
{
........
	u32			timeout = 5000;
........
	dwc3_writel(dep->regs, DWC3_DEPCMD, cmd);
	do {
		reg = dwc3_readl(dep->regs, DWC3_DEPCMD);
		if (!(reg & DWC3_DEPCMD_CMDACT)) {
			cmd_status = DWC3_DEPCMD_STATUS(reg);

			switch (cmd_status) {
			case 0:
				ret = 0;
				break;
			case DEPEVT_TRANSFER_NO_RESOURCE:
				dev_WARN(dwc->dev, "No resource for %s\n",
					 dep->name);
				ret = -EINVAL;
				break;
			case DEPEVT_TRANSFER_BUS_EXPIRY:
				/*
				 * SW issues START TRANSFER command to
				 * isochronous ep with future frame interval. If
				 * future interval time has already passed when
				 * core receives the command, it will respond
				 * with an error status of 'Bus Expiry'.
				 *
				 * Instead of always returning -EINVAL, let's
				 * give a hint to the gadget driver that this is
				 * the case by returning -EAGAIN.
				 */
				ret = -EAGAIN;
				break;
			default:
				dev_WARN(dwc->dev, "UNKNOWN cmd status\n");
			}

			break;
		}
	} while (--timeout);

	if (timeout == 0) {
		ret = -ETIMEDOUT;
		cmd_status = -ETIMEDOUT;
	}
........
}

原因分析

从上面的代码可以看出,是读usb控制器的某个寄存器5000次都没有得到目标值

1. 检查函数传参以及代码流程

添加log,发现正常和异常时传入的参数和内部走的代码流程完全一致, 排除函数内部问题

2. 检查调用逻辑

增加dump_statck(),查看流程,就是正常的probe流程

[    6.881962][    T1] Call trace:
[    6.881970][    T1]  dump_backtrace+0x0/0x1c8
[    6.881974][    T1]  show_stack+0x1c/0x2c
[    6.881981][    T1]  dump_stack_lvl+0xdc/0x12c
[    6.881984][    T1]  dump_stack+0x1c/0x64
[    6.881990][    T1]  dwc3_send_gadget_ep_cmd+0x5e0/0xa7c
[    6.881994][    T1]  __dwc3_gadget_ep_enable+0x3c8/0x568
[    6.881998][    T1]  __dwc3_gadget_start+0x1d8/0x5a8
[    6.882002][    T1]  dwc3_gadget_pullup+0xcc/0x310
[    6.882007][    T1]  usb_gadget_connect+0x3c/0x10c
[    6.882010][    T1]  udc_bind_to_driver+0x150/0x184
[    6.882012][    T1]  usb_gadget_probe_driver+0xa8/0x184
[    6.882015][    T1]  gadget_dev_desc_UDC_store+0xec/0x138
[    6.882020][    T1]  configfs_write_file+0x104/0x154
[    6.882023][    T1]  vfs_write+0x168/0x390
[    6.882026][    T1]  ksys_write+0x78/0xe8
[    6.882028][    T1]  __arm64_sys_write+0x20/0x30
[    6.882032][    T1]  el0_svc_common+0xc0/0x23c
[    6.882035][    T1]  do_el0_svc+0x28/0x88
[    6.882038][    T1]  el0_svc+0x14/0x24
[    6.882041][    T1]  el0_sync_handler+0x88/0xec
[    6.882044][    T1]  el0_sync+0x1a8/0x1c0

3. 增加延时

既然无法从原有代码找到问题,尝试用其他方法优化,首先根据代码是循环读取5000次,中间没有其他操作,说明需要时间,
尝试在while前增加延时,看是否可以优化。
结果:没有效果

4. 配置成usb3.0

由于之前做过的rk3588的两个项目都没有此问题,其中一个是结合外置type-c控制芯片配置成全功能接口(虽然硬件上只有usb2.0),另一个是配置成usb3.0接口。

他们都没有disabled掉usbdp相关的phy。

打开usbdp相关的phy
&usbdp_phy0 {
	status = "okay";
};

&usbdp_phy0_dp {
	status = "okay";
};

&usbdp_phy0_u3 {
	status = "okay";
};

结果:没有效果

删除maximum-speed

从文档中看到,配置maximum-speed = "high-speed",通知dwc3驱动将usb限制为USB2.0 only
在上一步的基础上,把这个配置删除。
结果:usb一直不能用

删除usbdrd_dwc3_0中phy的配置

在上一步的基础上,结合另外两个项目的配置方式删除usbdrd_dwc3_0中phy的配置

&usbdrd_dwc3_0 {
	status = "okay";
	dr_mode = "otg";
    extcon = <&u2phy0>;
};

结果:有效
这个配置按照文档中的说法属于type-c to usb3.0/dp的配置,后来又经过测试,可以disable掉usbdp_phy0_dp,最终的配置如下:

&usbdrd3_0 {
	status = "okay";
};

&usbdrd_dwc3_0 {
	status = "okay";
	dr_mode = "otg";
    extcon = <&u2phy0>;
};

&u2phy0 {
	status = "okay";
};

&u2phy0_otg {
	status = "okay";
};
&usbdp_phy0 {
	status = "okay";
};

&usbdp_phy0_dp {
	status = "okay";
};

&usbdp_phy0_u3 {
	status = "disabled";
};

总结

经过这个问题,说明rk3588 type-c to usb2.0功能有bug,或者文档给出的参考配置不完整

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值