Rockchip RK3588 - USB基础 & 调试

开发板 :NanoPC-T6开发板eMMC256GBLPDDR416GB
显示屏 :15.6英寸HDMI接口显示屏u-boot2017.09linux6.1
----------------------------------------------------------------------------------------------------------------------------

有关USB的发展历史,以及接口规范这一节我们就不再重复介绍了,没有相关基础的话可以参考我之前写过的文章:

  • linux驱动移植-usb驱动基础》;
  • Rockchip RK3399 - USB基础》;

一、RK3588 USB介绍

1.1 USB控制器

RK3588 支持4个独立的USB控制器,不同控制器相互独立:

  • 两个USB2.0 HOST(EHCI&OHCI);
  • 两个USB3.0 OTG(DWC3/xHCI);
  • 一个USB3.0 HOST(xHCI);只支持USB3.0功能,不向下兼容USB2.0;

其中:

  • EHCI/OHCI: 表示该USB控制器集成了EHCI控制器和OHCI控制器;
  • DWC3/xHCI:表示该USB控制器集成了DWC3控制器和 xHCI控制器;
  • USB3.0 物理层传输速率为5GbpsUSB2.0物理层传输速率为480Mbps;
1.1.1 USB2.0 HOST(EHCI/OHCI)

支持高速 (480Mbps),全速 (12Mbps) 和低速 (1.5Mbps),USB2.0 Host控制器的框图如下图所示;

Rockchip RK3588 - USB基础 & 调试_第1张图片

内部有EHCIOHCI Host Controller

  • OHCI支持USB1.0USB1.1;
  • EHCI支持USB2.0

Port Routing Control: 用于选择用EHCI还是OHCI

USB2.0 Host控制器连接到USB2.0 PHY

EHCIOHCI Rockchip采用linux内核Generic驱动,一般开发时只需要对设备树作相应配置,即可正常工作。

为了同时支持USB1.0USB1.1USB2.0,就需要同时用到EHCIOHCI,因此需要在设备树中把这两个USB控制器都打开,如:

&usb_host0_ehci {
        status = "okay";
};

&usb_host0_ohci {
        status = "okay";
}

&usb_host1_ehci {
        status = "okay";
};

&usb_host1_ohci {
        status = "okay";
};

这样配置之后,RK3588 的两个USB2.0 HOST控制器就使能了,并且同时支持EHCIOHCI

1.1.2 USB3.0 OTG(DWC3/xHCI)

RK3588 USB3.0 OTG使用Synopsys方案,即xHCI扩展的DWC3控制器,Host功能在xHCI框架下实现,而Device功能由DWC3扩展部分实现。

DWC3具有以下特性:

  • 支持Control/Bulk(including stream)/Interrupt/Isochronous传输方式;
  • USB3.0支持同时执行INOUT传输,带宽达到8Gbps
  • 支持描述符缓存 (Descriptor Caching) 和数据预取 (Data Pre-fetching);
  • Device模式支持的IN端点数量和OUT端点数量请参考芯片手册;
  • 支持硬件自动处理ERDYburst
  • 支持端点批量流传输 (bulk stream);
  • 支持USB3.0 DRD (Dual-Role Device) 特性;
  • 支持根据OTG ID状态切换DeviceHost模式;
  • 对于支持Type-C的芯片,支持UFP/DFP角色交换;
  • 不支持SRP (session request protocol),HNP(hostnegotiation protocol)和RSP (Role Swap Protocol);

USB3.0 xHCI Host特性:

  • 最多可以连接64个外设;
  • 支持一个中断器;
  • 支持一个USB2.0端口和一个USB3.0端口;
  • 支持USB3.0/USB2.0并发传输,带宽达到8Gbps
  • 支持标准和开源的xHCI驱动;
  • 部分芯片支持xHCI Debug Capability

USB3.0 OTG控制器的框图如下图所示;

Rockchip RK3588 - USB基础 & 调试_第2张图片

USB3.0 OTG具有USB3.0 OTG(USB PeripheralUSB Host)功能,且向下兼容USB2.0 OTG功能,大传输速率为5Gbps

由于USB3.0 HOST控制器为xHCI,集成于DWC3 OTG IP中,所以不用单独为其配置设备树,只需要配置DWC3,并且设置DWC3dr_mode属性为dr_mode = otg或者dr_mode = host,即可以使能xHCI控制器。

1.1.3 USB3.0 HOST(xHCI)

USB3.0 HOST 控制器只支持USB3.0功能,无法支持USB2.0(因为没有带USB2.0 PHY)。因此,USB3.0 HOST 需要与USB2.0 HOST 控制器组合,以支持完整的USB3.0协议功能。

1.2 USB PHY

RK3588支持7个独立的USB PHY

  • 4个USB2.0 PHY:在设备树中分别叫做u2phy0u2phy1u2phy2u2phy3;
  • 2个 USB3.0/DP Combo PHY:在设备树中分别叫做usbdp_phy0usbdp_phy1
  • 1 个USB3.0/SATA/PCIe Combo PHY:在设备树中叫做combphy2_psu

其中:

  • USB3.0/DP Combo PHY支持4 x lanes,可以同时支持USB3.0 + DP 2 x lanes
  • USB3.0/SATA/PCIe Combo PHY在同一时刻,只能支持一种工作模式,也即USB3.0SATA/PCIe接口是互斥的;

Rockchip采⽤的USB PHY主要有如下几种:

  • USB2.0 PHY [Vendor: Innosilicon];RK3588使用的4个USB2.0 PHY正是采用这个;
  • USB2.0 PHY [Vendor: Synopsys]; Synopsys USB2.0 PHY只⽤于较早的⼏款芯⽚(RK3066/RK3188/RK3288),当前的主流芯⽚和后续的芯⽚USB2.0 PHY都是采⽤Innosilicon提供的IP
  • USB3.0 PHY [Vendor: Innosilicon];Inno USB3.0 PHY只⽀持Super-speed,没有向下兼容High-Speed,所以需要和Inno USB2.0 PHY组成⼀个Combo PHYRK3588使用的2个 USB3.0/DP Combo PHY正是采用这个;
  • USB3.0 PHY [Vendor: naneng]:RK3588使用的 USB3.0/SATA/PCIe Combo PHY正是采用这个;
  • Type-C PHY [Vendor: Cadence]。
1.2.1 USB2.0 PHY

USB2.0 PHY支持1个port和2个port两种设计,如下图是支持2个port的框图;

Rockchip RK3588 - USB基础 & 调试_第3张图片

Host Port:通过UTMI+ 连接到USB2.0 Host控制器;

OTG Port:通过UTMI+连接USB3.0/2.0 OTG控制器的USB2.0逻辑模块;

RK3588为例,使用的4个USB2.0 PHY均是采用Innosilicon IP,每个USB2.0 PHY都只有1个port端口;

  • u2phy0:包含u2phy0_otg
  • u2phy1:包含u2phy1_otg
  • u2phy2:包含u2phy2_host
  • u2phy3:包含u2phy3_host
1.2.2 USB3.0/DP Combo PHY

RK3588使用的2个 USB3.0/DP Combo PHY均是采用Innosilicon IPInno USB3.0 PHY只⽀持Super-speed,没有向下兼容High-Speed,所以需要和Inno USB2.0 PHY组成⼀个Combo PHY。如下图是⼀个典型的USB3.0 OTG控制器架构图;

Rockchip RK3588 - USB基础 & 调试_第4张图片

注意:图中由下方的USB3.0 PHY可以看做是个 USB3.0/DP Combo PHY

1.2.3 USB3.0/SATA/PCIe Combo PHY

RK3588使用的 USB3.0/SATA/PCIe Combo PHY采用NaNeng IP。只能支持USB3.0,不向下兼容USB2.0。并且,在芯片内部设计时,没有与USB2.0 PHY 组合。

1.3 USB控制器和USB PHY关系
1.3.1 连接示意

RK3588 USB控制器和USB PHY的连接示意图如下:

USB 接口类型(仅仅示例,接口类型可调整) USB 控制器 USB PHY
USB3.0 Type-C0 USB3.0 OTG0 (DWC3&xHCI) USB3.0/DP Combo PHY0 + USB2.0 PHY0
USB3.0 Type-C1 USB3.0 OTG1 (DWC3&xHCI) USB3.0/DP Combo PHY1 + USB2.0 PHY1
USB2.0 HOST0 Type-A USB2.0 HOST0(EHCI&OHCI) USB2.0 PHY2
USB2.0 HOST1 Type-A USB2.0 HOST1(EHCI&OHCI) USB2.0 PHY3
USB3.0 HOST2 Type-A USB3.0 HOST2 (xHCI) USB3.0/SATA/PCIe Combo PHY2

可视化如下:

Rockchip RK3588 - USB基础 & 调试_第5张图片

由图可以看出,RK3588最多可以同时支持2个全功能的USB3.0 Type-C 接口,2个USB2.0 Type-A 接口,1 个 USB3.0 Type-A接口(不向下兼容USB2.0);

  • USB3.0 OTG控制器 与DP控制器复用USB3.1/DP Combo PHY,可组成全功能的Type-C接口,也可以拆分独立使用(如:常见的USB3.0 Type-A接口 + DP 接口[2 x lanes]);
    • USB3.0/DP Combo PHY只能支持USB3.0,不向下兼容USB2.0。所以,它们在芯片内部设计时,实际是与USB2.0 PHY组合,以支持完整的USB3.0协议功能。其中:
    • USB3.0/DP Combo PHY0固定与USB2 PHY0组合;
    • USB3.0/DP Combo PHY1固定与USB2 PHY1组合;
  • USB3.0 HOST2 控制器只支持USB3.0功能,无法支持USB2.0(因为没有带USB2.0 PHY)。可以将USB3.0 HOST2USB2.0 HOST0 USB2.0 HOST1组合,作为一个完整的USB3.0 Type-A 接口;
  • USB3.0/SATA/PCIe Combo PHY只能支持USB3.0,不向下兼容USB2.0。并且,在芯片内部设计时,没有与USB2.0 PHY 组合。因此,USB3.0 HOST2 需要与USB2.0 HOST0/1 接口(二选一)组合,以支持完整的USB3.0协议功能;

需要注意的是,RK3588 USB支持的接口类型并不局限于图中所描述的USB Type-C/A接口类型,而是可以支持所有常见的USB 接口,包括USB2.0/3.0 Type-CUSB2.0/3.0 Type-AMicro USB2.0/3.0等,具体信息请参考RK3588 USB支持的接口类型。

为了适配不同的USB电路设计和接口类型,Linux内核USB驱动已经做了软件兼容,开发者只需要根据产品的USB硬件电路,对Linux USB DTS进行正确配置,即可使能对应的USB接口功能。

1.3.2 引脚定义

RK3588 USB控制器和芯片端USB传输数据的pin脚的对应关系如下表所示:

USB控制器/Pin脚 RK3588 USB data pin
USB2.0 HOST0 USB20_HOST0_DP/USB20_HOST0_DM
USB2.0 HOST1 USB20_HOST1_DP/USB20_HOST1_DM
USB3.0 OTG0 TYPEC0_USB20_OTG_DP/TYPEC0_USB20_OTG_DM,
TYPEC0_SSRX1P/TYPEC0_SSRX1N, TYPEC0_SSTX1P/TYPEC0_SSTX1N,
TYPEC0_SSRX2P/TYPEC0_SSRX2N, TYPEC0_SSTX2P/TYPEC0_SSTX2N
USB3.0 OTG1 TYPEC1_USB20_OTG_DP/TYPEC1_USB20_OTG_DM,
TYPEC1_SSRX1P/TYPEC1_SSRX1N, TYPEC1_SSTX1P/TYPEC1_SSTX1N
TYPEC1_SSRX2P/TYPEC1_SSRX2N, TYPEC1_SSTX2P/TYPEC1_SSTX2N
USB3.0 HOST2 USB30_2_SSTXP/USB30_2_SSTXN
USB30_2_SSRXP/USB30_2_SSRXN

二、硬件原理图

这里我使用的开发板型号是NanoPC-T6,开发板如下图所示;

Rockchip RK3588 - USB基础 & 调试_第6张图片

USB资源如下:

  • USB-C/DP: 一个全功能USB3.0 Type‑C接口, 支持USB3.0数据传输和DP显示输出,分辨率高达4Kp60

  • USB3.0: 一个USB3.0 Type-A

2.1 USB3.0 Type‑C

我们使用的开发板NanpiPC-T6USB3.0/DP Combo PHY0USB2 PHY0物理接口被设计为USB3.0 Type-C,如下图所示:

Rockchip RK3588 - USB基础 & 调试_第7张图片

友善的这块电路实际上是参考Rockchip官方的Type-C USB3.0/DP全功能硬件电路。

需要注意的是这里TYPEC0_USB20_VBUSDET引脚是连接到VCCA_3V3_S0。至于为啥这么设计,官方给出了说明:

  • 为了支持高压充电功能,同时降低硬件电路的风险,TYPEC0_USB20_VBUSDET不要连接Type-C接口的VBUS,固定上拉到3.3V即可(TYPEC0_USB20_VBUSDET 连接到VCCA_3V3_S0),但不能悬空;
  • Type-C0设计为支持PD功能的Type-C接口时,即支持外置Type-C控制器芯片(如:FUSB302或者HUSB311),则TYPEC0_USB20_VBUSDET固定上拉到 VCCA_3V3_S0,软件驱动可以通过Type-C控制器芯片的CC检测USB Device的连接和
    断开;
2.1.1 电源接线

上图中供电依次为VDDA_0V85_S0VCCA_1V8_S0VDDA_0V75_S0VCCA_3V3_S0,这些电源均是由电源芯片RK806输出。

(1) 电源VDDA_0V85_S0RK806第10号引脚提供的;

(2) 电源VCCA_1V8_S0RK806第60号引脚提供的;

(3) 电源VDDA_0V75_S0RK806第11号引脚提供的;

(4) 电源VCCA_3V3_S0RK806第63号引脚提供的。

2.1.2 Type-C接口接线

其中TYPEC0_SSTX1PTYPEC0_SSTX1NTYPEC0_SSRX1PTYPEC0_SSRX1NTYPEC0_SSTX2PTYPEC0_SSTX2NTYPEC0_SSRX2PTYPEC0_SSRX2NTYPEC0_SBU1TYPEC0_SBU2TYPEC0_USB20_OTG_DMTYPEC0_USB20_OTG_DP连接到开发板上的TYPE-CTYPE-CUSB3.0 Type-C接口;

RK3588 USB3.0/DP Combo PHY0 USB2.0 PHY0 USB3.0 Type-C
TYPEC0_SSTX1P/DP0_TX1P TYPEC0_SSTX1P SSTX1_P
TYPEC0_SSTX1N/DP0_TX1N TYPEC0_SSTX1N SSTX1_N
TYPEC0_SSRX1P/DP0_TX0P TYPEC0_SSRX1P SSRX1_P
TYPEC0_SSRX1N/DP0_TX0N TYPEC0_SSRX1N SSRX1_N
TYPEC0_SSTX2P/DP0_TX3P TYPEC0_SSTX2P SSTX2_P
TYPEC0_SSTX2N/DP0_TX3N TYPEC0_SSTX2N SSTX2_N
TYPEC0_SSRX2P/DP0_TX2P TYPEC0_SSRX2P SSRX2_P
TYPEC0_SSRX2N/DP0_TX2N TYPEC0_SSRX2N SSRX2_N
TYPEC0_SBU1/DP0_AUXP TYPEC0_SBU1 SBU1
TYPEC0_SBU2/DP0_AUXN TYPEC0_SBU2 SBU2
GPIO4_A6 TYPEC0_SBU1_DC SBU1
GPIO4_A7 TYPEC0_SBU2_DC SBU2
TYPEC0_USB20_OTG_DM TYPEC0_OTG_DM D-
TYPEC0_USB20_OTG_DP TYPEC0_OTG_DP D+
TYPEC0_USB20_OTG_DM TYPEC0_OTG_DM DM
TYPEC0_USB20_OTG_DP TYPEC0_OTG_DP DP
USB20_AVDD_3V3 TYPEC0_USB20_VBUSDET
TYPEC_CC1
TYPEC_CC2

如下图所示:

Rockchip RK3588 - USB基础 & 调试_第8张图片

电源VBUS5V0_TYPECSY6280AAC提供的,其输入端为VCC5V0_SYS。由TYPEC5V_PWREN_H(GPIO1_D2)引脚使能;

Rockchip RK3588 - USB基础 & 调试_第9张图片
2.1.3 fusb302

fusb302是可编程的USB Type-C控制器,支持识别各种USB设备和对应的工作状态,且支持最高100WPD协议。

其具有一下主要特征:

  • 具备自主DRP切换的双重角色功能;
  • 根据已连接的设备选择作为Host(主机)或Device(设备)进行连接;
  • 通过软件配置为Host(主机)、Device(设备)或双重角色;
  • 支持USB功率传递(PD)2.0:
Rockchip RK3588 - USB基础 & 调试_第10张图片

其引脚如下:

引脚 类型 功能
CC1/CC2 I/O Type-C连接器的配置通道(CC)引脚。最初用于确定插入事件发生以及插入的方向。连接后的功能取决于检测到的操作模式。 作为主机运行时:
1)设置可被连接设备感知的VBUS的允许充电电流;
2)用于与使用USB BMC Power Delivery的设备进行通信;
3)用于检测已发生的拔出事件 作为设备运行时:
4)指示来自连接的主机的允许下沉电流。用于与使用USB BMC Power Delivery的设备进行通信主要用来 PD协议通信或其他:
VBUS Input 当作为面向上行端口(设备)运行时,该引脚可用于设备插入和拔出的检测。
VCONN Power Switch 要将调节输入电源切换到正确的CC引脚作为VCONN以为USB3.1完整功能电缆和其他配件供电。
INIT Open-Drain Output 中断输出,当有事件发生时,用于通知处理器读取I2C寄存器数据。如:插入/拔出typeC,INIT_N都会拉低一下。
SCL Input I2C时钟
SDA Open-Drain I/O I2C数据引脚

INT连接的是RK3588GPIO0_D3引脚,I2C通信使用的是I2C6

由于这篇文章不是fusb302的专栏,所以就不细说了,具体参考《PD快充 - fusb302驱动调试笔记》。

2.2 USB3.0 Type-A

我们使用的开发板NanpiPC-T6USB3.0/DP Combo PHY1USB2 PHY1物理接口被设计为USB3.0 Type-A,如下图所示:

Rockchip RK3588 - USB基础 & 调试_第11张图片

友善的这块电路实际上是参考Rockchip官方的Type-C to Type-A USB 3.1/DP硬件电路。

需要注意的是这里TYPEC1_USB20_VBUSDET引脚是悬空的,至于为啥这么设计,官方给出了说明:

  • 如果USB OTG有作Device/HOST的应用场景,建议TYPEC0_OTG_VBUSDET通过30KΩ的电阻串联到USB Type-A接口的VBUS
  • 然而友善这里将TYPEC1_USB20_VBUSDET引脚悬空处理,USB Type-A接口大概率只能作为HOST mode使用。
2.2.1 Type-A接口接线

其中TYPEC1_SSTX1PTYPEC1_SSTX1NTYPEC1_SSRX1PTYPEC1_SSRX1NTYPEC1_USB20_OTG_DMTYPEC1_USB20_OTG_DP连接到USB3USB3USB3.0 Type-A接口;

RK3588 USB3.0 Type-C PHY1 USB2.0 PHY1 USB3.0 Type-A
TYPEC1_SSTX1P/DP1_TX1P TYPEC1_SSTX1P TX+
TYPEC1_SSTX1N/DP1_TX1N TYPEC1_SSTX1N TX-
TYPEC1_SSRX1P/DP1_TX0P TYPEC1_SSRX1P RX+
TYPEC1_SSRX1N/DP1_TX0N TYPEC1_SSRX1N RX-
TYPEC1_USB20_OTG_DM TYPEC1_OTG_DM D-
TYPEC1_USB20_OTG_DP TYPEC1_OTG_DP D+

如下图所示:

Rockchip RK3588 - USB基础 & 调试_第12张图片

电源VCC5V0_USB30_HOST2SY6280AAC提供的,其输入端为VCC5V0_SYS。由USB_HOST_PWREN_H(GPIO4_B0)引脚使能。

USB3.0 OTG控制器工作在Device mode,关闭VBUS输出。当USB3.0 OTG控制器工作在HOST mode,打开VBUS输出。此外,稳压芯片SY6280AAC的输出电流由OCB pin 连接的电阻决定,最大电流Ilim(A)=6800/Rset(ohm) VBUS输出限流为1A.

三、设备树

设备树配置参考文档:

  • Documentation/devicetree/bindings/usb/snps,dwc3.yaml
  • Documentation/devicetree/bindings/usb/generic-ohci.yaml
  • Documentation/devicetree/bindings/usb/generic-ehci.yaml
  • Documentation/devicetree/bindings/connector/usb-connector.yaml
  • Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.yaml
  • Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml
  • Documentation/devicetree/bindings/phy/phy/phy-rockchip-naneng-combphy.txt

RK3588 USB接口和USB dts节点的对应关系:

USB 接口类型(仅仅示例) USB控制器DTS 节点 USB PHY DTS 节点
USB3.0 Type-C0
对应开发板上标号为USB-C/DP的接口
USB3.0 OTG0 (DWC3&xHCI)
- usbdrd3_0
- usbdrd_dwc3_0
USB3.0/DP Combo PHY0 + USB2.0 PHY0
- u2phy0
- u2phy0_otg
- usbdp_phy0
- usbdp_phy0_u3
USB3.0 Type-C1
对应开发板上标号为USB3.0的接口,只不过接口类型被做成了Type-A
USB3.0 OTG1 (DWC3&xHCI)
- usbdrd3_1
- usbdrd_dwc3_1
USB3.0/DP Combo PHY1 + USB2.0 PHY1
- u2phy1
- u2phy1_otg
- usbdp_phy1
- usbdp_phy1_u3
USB2.0 HOST0 Type-A USB2.0 HOST0(EHCI&OHCI)
- usb_host0_ehci
- usb_host0_ohci
USB2.0 PHY2
- u2phy2
- u2phy2_host
USB2.0 HOST1 Type-A USB2.0 HOST1(EHCI&OHCI)
- usb_host1_ehci
- usb_host1_ohci
USB2.0 PHY3
- u2phy3
- u2phy3_host
USB3.0 HOST2 Type-A USB3.0 HOST2 (xHCI)
- usbhost3_0
- usbhost_dwc3_0
USB3.0/SATA/PCIe Combo PHY2
- combphy2_psu
3.1 NaniPC-T6设备树

在《Rockchip RK3588 - 移植uboot 2017.09 & linux 6.1(友善之家脚本方式)》我们介绍了友善内核编译过程,在arch/arm64/Makefile文件指定了如何生成resource.img文件。

DTBS := rk3*-nanopi*-rev*.dtb

# 调用scripts/mkimg编译生成resource.img(由设备树、图片资源文件组成,不包含内核)
nanopi4-images: dtbs kernel.img $(LOGO) $(LOGO_KERNEL)
        $(Q)$(srctree)/scripts/mkimg --dtb $(DTBS) --keep-dtb-name

可以看到NaniPC-T6友善提供的内核源码默认编译使用的设备树文件包括rk3*-nanopi*-rev*.dtb,对于RK3588而言具体包含以下文件:

root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588/kernel-rk3588# ls arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev*.dtb
arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev01.dtb  arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev04.dtb
arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev02.dtb  arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev05.dtb
arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev03.dtb  arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev09.dtb

rk3588-nanopi6-rev09.dts为例,文件引入了rk3588.dtsi以及rk3588-nanopi6-common.dtsi

#include "rk3588.dtsi"
#include "rk3588-nanopi6-common.dtsi"
3.2 USB控制器

USB3.0 OTG0(DWC3/xHCI)、USB2.0 HOST0/1(EHCI&OHCI)、USB3.0 HOST2(xHCI)的dtsi配置放在arch/arm64/boot/dts/rockchip/rk3588s.dtsi

USB3.0 OTG1(DWC3/xHCI)的dtsi配置放在arch/arm64/boot/dts/rockchip/rk3588.dtsi,这个文件包含了rk3588s.dtsi

因为USB DTSI节点配置的是USB控制器和PHY的公共资源和属性,建议开发者不要改动。

#include "rk3588s.dtsi"
3.2.1 USB2.0 HOST0(EHCI&OHCI)

USB2.0 HOST0控制器设备节点usb_host0_ehciusb_host0_ohci定义在arch/arm64/boot/dts/rockchip/rk3588s.dtsi

usb_host0_ehci: usb@fc800000 {
		compatible = "rockchip,rk3588-ehci", "generic-ehci";
		reg = <0x0 0xfc800000 0x0 0x40000>;
		interrupts = ;
		clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST_ARB0>, <&u2phy2>;
		clock-names = "usbhost", "arbiter", "utmi";
		companion = <&usb_host0_ohci>;
		phys = <&u2phy2_host>;
		phy-names = "usb2-phy";
		power-domains = <&power RK3588_PD_USB>;
		status = "disabled";
};

usb_host0_ohci: usb@fc840000 {
		compatible = "generic-ohci";
		reg = <0x0 0xfc840000 0x0 0x40000>;
		interrupts = ;
		clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST_ARB0>, <&u2phy2>;
		clock-names = "usbhost", "arbiter", "utmi";
		phys = <&u2phy2_host>;
		phy-names = "usb2-phy";
		power-domains = <&power RK3588_PD_USB>;
		status = "disabled";
};
3.2.2 USB2.0 HOST1(EHCI&OHCI)

USB2.0 HOST1控制器设备节点usb_host1_ehciusb_host1_ohci定义在arch/arm64/boot/dts/rockchip/rk3588s.dtsi

usb_host1_ehci: usb@fc880000 {
		compatible = "rockchip,rk3588-ehci", "generic-ehci";
		reg = <0x0 0xfc880000 0x0 0x40000>;
		interrupts = ;
		clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST_ARB1>, <&u2phy3>;
		clock-names = "usbhost", "arbiter", "utmi";
		companion = <&usb_host1_ohci>;
		phys = <&u2phy3_host>;
		phy-names = "usb2-phy";
		power-domains = <&power RK3588_PD_USB>;
		status = "disabled";
};

usb_host1_ohci: usb@fc8c0000 {
		compatible = "generic-ohci";
		reg = <0x0 0xfc8c0000 0x0 0x40000>;
		interrupts = ;
		clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST_ARB1>, <&u2phy3>;
		clock-names = "usbhost", "arbiter", "utmi";
		phys = <&u2phy3_host>;
		phy-names = "usb2-phy";
		power-domains = <&power RK3588_PD_USB>;
		status = "disabled";
};
3.2.3 USB3.0 OTG0(DWC3/xHCI)

USB3.0 OTG0(DWC3/xHCI)控制器设备节点usbdrd3_0,定义在arch/arm64/boot/dts/rockchip/rk3588s.dtsi

usbdrd3_0: usbdrd3_0 {
		compatible = "rockchip,rk3588-dwc3", "rockchip,rk3399-dwc3";
		clocks = <&cru REF_CLK_USB3OTG0>, <&cru SUSPEND_CLK_USB3OTG0>,
				 <&cru ACLK_USB3OTG0>;
		clock-names = "ref", "suspend", "bus";
		#address-cells = <2>;
		#size-cells = <2>;
		ranges;
		status = "disabled";

		usbdrd_dwc3_0: usb@fc000000 {
				compatible = "snps,dwc3";
				reg = <0x0 0xfc000000 0x0 0x400000>;
				interrupts = ;
				power-domains = <&power RK3588_PD_USB>;
				resets = <&cru SRST_A_USB3OTG0>;
				reset-names = "usb3-otg";
				dr_mode = "otg";
				phys = <&u2phy0_otg>, <&usbdp_phy0_u3>;
				phy-names = "usb2-phy", "usb3-phy";
				phy_type = "utmi_wide";
				snps,dis_enblslpm_quirk;
				snps,dis-u1-entry-quirk;
				snps,dis-u2-entry-quirk;
				snps,dis-u2-freeclk-exists-quirk;
				snps,dis-del-phy-power-chg-quirk;
				snps,dis-tx-ipgap-linecheck-quirk;
				snps,parkmode-disable-ss-quirk;
				quirk-skip-phy-init;
				status = "disabled";
		};
};
3.2.4 USB3.0 OTG1(DWC3/xHCI)

USB3.0 OTG1(DWC3/xHCI)控制器设备节点usbdrd3_1,定义在arch/arm64/boot/dts/rockchip/rk3588.dtsi

usbdrd3_1: usbdrd3_1 {
		compatible = "rockchip,rk3588-dwc3", "rockchip,rk3399-dwc3";
		clocks = <&cru REF_CLK_USB3OTG1>, <&cru SUSPEND_CLK_USB3OTG1>,
				 <&cru ACLK_USB3OTG1>;
		clock-names = "ref", "suspend", "bus";
		#address-cells = <2>;
		#size-cells = <2>;
		ranges;
		status = "disabled";

		usbdrd_dwc3_1: usb@fc400000 {
				compatible = "snps,dwc3";
				reg = <0x0 0xfc400000 0x0 0x400000>;
				interrupts = ;
				power-domains = <&power RK3588_PD_USB>;
				resets = <&cru SRST_A_USB3OTG1>;
				reset-names = "usb3-otg";
				dr_mode = "host";
				phys = <&u2phy1_otg>, <&usbdp_phy1_u3>;
				phy-names = "usb2-phy", "usb3-phy";
				phy_type = "utmi_wide";
				snps,dis_enblslpm_quirk;
				snps,dis-u1-entry-quirk;
				snps,dis-u2-entry-quirk;
				snps,dis-u2-freeclk-exists-quirk;
				snps,dis-del-phy-power-chg-quirk;
				snps,dis-tx-ipgap-linecheck-quirk;
				snps,parkmode-disable-ss-quirk;
				status = "disabled";
		};
};
3.2.5 USB3.0 HOST2(xHCI)

USB3.0 HOST2(xHCI)控制器设备节点usbhost3_0,定义在arch/arm64/boot/dts/rockchip/rk3588s.dtsi

usbhost3_0: usbhost3_0 {
		compatible = "rockchip,rk3588-dwc3", "rockchip,rk3399-dwc3";
		clocks = <&cru REF_CLK_USB3OTG2>, <&cru SUSPEND_CLK_USB3OTG2>,
				 <&cru ACLK_USB3OTG2>, <&cru CLK_UTMI_OTG2>,
				 <&cru PCLK_PHP_ROOT>, <&cru CLK_PIPEPHY2_PIPE_U3_G>;
		clock-names = "ref", "suspend", "bus", "utmi", "php", "pipe";
		#address-cells = <2>;
		#size-cells = <2>;
		ranges;
		status = "disabled";

		usbhost_dwc3_0: usb@fcd00000 {
				compatible = "snps,dwc3";
				reg = <0x0 0xfcd00000 0x0 0x400000>;
				interrupts = ;
				resets = <&cru SRST_A_USB3OTG2>;
				reset-names = "usb3-host";
				dr_mode = "host";
				phys = <&combphy2_psu PHY_TYPE_USB3>;
				phy-names = "usb3-phy";
				phy_type = "utmi_wide";
				snps,dis_enblslpm_quirk;
				snps,dis-u2-freeclk-exists-quirk;
				snps,dis-del-phy-power-chg-quirk;
				snps,dis-tx-ipgap-linecheck-quirk;
				snps,dis_rxdet_inp3_quirk;
				snps,parkmode-disable-ss-quirk;
				status = "disabled";
		};
};
3.2.6 使能

arch/arm64/boot/dts/rockchip/rk3588-nanopi6-common.dtsi中,使能了:

  • USB2.0 HOST0(EHCI&OHCI);

  • USB3.0 OTG0(DWC3/xHCI)

  • USB3.0 HOST2(xHCI)

# USB2.0 HOST0(EHCI&OHCI)
&usb_host0_ehci {
        status = "okay";
};

&usb_host0_ohci {
        status = "okay";
};

# USB3.0 OTG0(DWC3/xHCI)
&usbdrd3_0 {
        status = "okay";
};

# USB3.0 HOST2(xHCI)
&usbhost3_0 {
        status = "disabled";
};

USB2.0 HOST1(EHCI&OHCI)、USB3.0 OTG1(DWC3/xHCI)arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev09.dts中有使能:

# USB2.0 HOST1(EHCI&OHCI)
&usb_host1_ehci {
        status = "okay";
};

&usb_host1_ohci {
        status = "okay";
};


# USB3.0 OTG1(DWC3/xHCI)
&usbdrd3_1 {
        status = "okay";
};
3.3 USB PHY

USB PHYUSB控制器具有一一对应的关系,需要成对配置。在芯片内部,USB PHY和控制器的连接关系,请参考1,3小节。在dtsi节点中,通过USB控制器节点的phys属性关联对应的USB PHY

USB2.0 PHY0/2/3USB3.0/DP Combo PHY0USB3.0/SATA/PCIe Combo PHYdtsi配置放在arch/arm64/boot/dts/rockchip/rk3588s.dtsi

USB2.0 PHY1USB3.0/DP Combo PHY1dtsi配置放在arch/arm64/boot/dts/rockchip/rk3588.dtsi

3.3.1 USB2.0 PHY0

USB2.0 PHY0包含1个端口设备节点为u2phy0_otg,定义在arch/arm64/boot/dts/rockchip/rk3588s.dtsi

usb2phy0_grf: syscon@fd5d0000 {
		compatible = "rockchip,rk3588-usb2phy-grf", "syscon",
					 "simple-mfd";
		reg = <0x0 0xfd5d0000 0x0 0x4000>;
		#address-cells = <1>;
		#size-cells = <1>;

		u2phy0: usb2-phy@0 {
				compatible = "rockchip,rk3588-usb2phy";
				reg = <0x0 0x10>;
				interrupts = ;
				resets = <&cru SRST_OTGPHY_U3_0>, <&cru SRST_P_USB2PHY_U3_0_GRF0>;
				reset-names = "phy", "apb";
				clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>;
				clock-names = "phyclk";
				clock-output-names = "usb480m_phy0";
				#clock-cells = <0>;
				rockchip,usbctrl-grf = <&usb_grf>;
				status = "disabled";

				u2phy0_otg: otg-port {
						#phy-cells = <0>;
						status = "disabled";
				};
		};
};
3.3.2 USB2.0 PHY1

USB2.0 PHY1包含1个端口设备节点为u2phy1_otg,定义在arch/arm64/boot/dts/rockchip/rk3588.dtsi

usb2phy1_grf: syscon@fd5d4000 {
		compatible = "rockchip,rk3588-usb2phy-grf", "syscon",
					 "simple-mfd";
		reg = <0x0 0xfd5d4000 0x0 0x4000>;
		#address-cells = <1>;
		#size-cells = <1>;

		u2phy1: usb2-phy@4000 {
				compatible = "rockchip,rk3588-usb2phy";
				reg = <0x4000 0x10>;
				interrupts = ;
				resets = <&cru SRST_OTGPHY_U3_1>, <&cru SRST_P_USB2PHY_U3_1_GRF0>;
				reset-names = "phy", "apb";
				clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>;
				clock-names = "phyclk";
				clock-output-names = "usb480m_phy1";
				#clock-cells = <0>;
				rockchip,usbctrl-grf = <&usb_grf>;
				status = "disabled";

				u2phy1_otg: otg-port {
						#phy-cells = <0>;
						status = "disabled";
				};
		};
};
3.3.3 USB2.0 PHY2

USB2.0 PHY2包含1个端口设备节点为u2phy2_host,定义在arch/arm64/boot/dts/rockchip/rk3588s.dtsi

usb2phy2_grf: syscon@fd5d8000 {
		compatible = "rockchip,rk3588-usb2phy-grf", "syscon",
					 "simple-mfd";
		reg = <0x0 0xfd5d8000 0x0 0x4000>;
		#address-cells = <1>;
		#size-cells = <1>;

		u2phy2: usb2-phy@8000 {
				compatible = "rockchip,rk3588-usb2phy";
				reg = <0x8000 0x10>;
				interrupts = ;
				resets = <&cru SRST_OTGPHY_U2_0>, <&cru SRST_P_USB2PHY_U2_0_GRF0>;
				reset-names = "phy", "apb";
				clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>;
				clock-names = "phyclk";
				clock-output-names = "usb480m_phy2";
				#clock-cells = <0>;
				status = "disabled";

				u2phy2_host: host-port {
						#phy-cells = <0>;
						status = "disabled";
				};
		};
};
3.3.4 USB2.0 PHY3

USB2.0 PHY3包含1个端口设备节点为u3phy3_host,定义在arch/arm64/boot/dts/rockchip/rk3588s.dtsi

usb2phy3_grf: syscon@fd5dc000 {
		compatible = "rockchip,rk3588-usb2phy-grf", "syscon",
					 "simple-mfd";
		reg = <0x0 0xfd5dc000 0x0 0x4000>;
		#address-cells = <1>;
		#size-cells = <1>;

		u2phy3: usb2-phy@c000 {
				compatible = "rockchip,rk3588-usb2phy";
				reg = <0xc000 0x10>;
				interrupts = ;
				resets = <&cru SRST_OTGPHY_U2_1>, <&cru SRST_P_USB2PHY_U2_1_GRF0>;
				reset-names = "phy", "apb";
				clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>;
				clock-names = "phyclk";
				clock-output-names = "usb480m_phy3";
				#clock-cells = <0>;
				status = "disabled";

				u2phy3_host: host-port {
						#phy-cells = <0>;
						status = "disabled";
				};
		};
};
3.3.5 USB3.0/DP Combo PHY0

USB3.0/DP Combo PHY0包含2个端口,对应设备节点分别为usbdp_phy0_dpusbdp_phy0_u1,定义在arch/arm64/boot/dts/rockchip/rk3588s.dtsi

usbdp_phy0: phy@fed80000 {
		compatible = "rockchip,rk3588-usbdp-phy";
		reg = <0x0 0xfed80000 0x0 0x10000>;
		rockchip,u2phy-grf = <&usb2phy0_grf>;
		rockchip,usb-grf = <&usb_grf>;
		rockchip,usbdpphy-grf = <&usbdpphy0_grf>;
		rockchip,vo-grf = <&vo0_grf>;
		clocks = <&cru CLK_USBDPPHY_MIPIDCPPHY_REF>,
				 <&cru CLK_USBDP_PHY0_IMMORTAL>,
				 <&cru PCLK_USBDPPHY0>,
				 <&u2phy0>;
		clock-names = "refclk", "immortal", "pclk", "utmi";
		resets = <&cru SRST_USBDP_COMBO_PHY0_INIT>,
				 <&cru SRST_USBDP_COMBO_PHY0_CMN>,
				 <&cru SRST_USBDP_COMBO_PHY0_LANE>,
				 <&cru SRST_USBDP_COMBO_PHY0_PCS>,
				 <&cru SRST_P_USBDPPHY0>;
		reset-names = "init", "cmn", "lane", "pcs_apb", "pma_apb";
		status = "disabled";

		usbdp_phy0_dp: dp-port {
				#phy-cells = <0>;
				status = "disabled";
		};

		usbdp_phy0_u3: u3-port {
				#phy-cells = <0>;
				status = "disabled";
		};
};
3.3.6 USB3.0/DP Combo PHY1

USB3.0/DP Combo PHY1包含2个端口,对应设备节点分别为usbdp_phy1_dpusbdp_phy1_u1,定义在arch/arm64/boot/dts/rockchip/rk3588.dtsi

usbdp_phy1: phy@fed90000 {
		compatible = "rockchip,rk3588-usbdp-phy";
		reg = <0x0 0xfed90000 0x0 0x10000>;
		rockchip,u2phy-grf = <&usb2phy1_grf>;
		rockchip,usb-grf = <&usb_grf>;
		rockchip,usbdpphy-grf = <&usbdpphy1_grf>;
		rockchip,vo-grf = <&vo0_grf>;
		clocks = <&cru CLK_USBDPPHY_MIPIDCPPHY_REF>,
				 <&cru CLK_USBDP_PHY1_IMMORTAL>,
				 <&cru PCLK_USBDPPHY1>,
				 <&u2phy1>;
		clock-names = "refclk", "immortal", "pclk", "utmi";
		resets = <&cru SRST_USBDP_COMBO_PHY1_INIT>,
				 <&cru SRST_USBDP_COMBO_PHY1_CMN>,
				 <&cru SRST_USBDP_COMBO_PHY1_LANE>,
				 <&cru SRST_USBDP_COMBO_PHY1_PCS>,
				 <&cru SRST_P_USBDPPHY1>;
		reset-names = "init", "cmn", "lane", "pcs_apb", "pma_apb";
		status = "disabled";

		usbdp_phy1_dp: dp-port {
				#phy-cells = <0>;
				status = "disabled";
		};

		usbdp_phy1_u3: u3-port {
				#phy-cells = <0>;
				status = "disabled";
		};
};
3.3.7 USB3.0/SATA/PCIe Combo PHY

USB3.0/SATA/PCIe Combo PHY对应的设备节点为combphy2_psu,定义在arch/arm64/boot/dts/rockchip/rk3588s.dtsi

combphy2_psu: phy@fee20000 {
		compatible = "rockchip,rk3588-naneng-combphy";
		reg = <0x0 0xfee20000 0x0 0x100>;
		#phy-cells = <1>;
		clocks = <&cru CLK_REF_PIPE_PHY2>, <&cru PCLK_PCIE_COMBO_PIPE_PHY2>,
				 <&cru PCLK_PHP_ROOT>;
		clock-names = "refclk", "apbclk", "phpclk";
		assigned-clocks = <&cru CLK_REF_PIPE_PHY2>;
		assigned-clock-rates = <100000000>;
		resets = <&cru SRST_P_PCIE2_PHY2>, <&cru SRST_REF_PIPE_PHY2>;
		reset-names = "combphy-apb", "combphy";
		rockchip,pipe-grf = <&php_grf>;
		rockchip,pipe-phy-grf = <&pipe_phy2_grf>;
		rockchip,pcie1ln-sel-bits = <0x100 1 1 0>;
		status = "disabled";
};
3.3.8 使能

arch/arm64/boot/dts/rockchip/rk3588-nanopi6-common.dtsi中,使能了:

  • USB2.0 PHY0

  • USB2.0 PHY2

  • USB3.0/DP Combo PHY0

  • USB3.0/SATA/PCIe Combo PHY

# USB2.0 PHY0
&u2phy0 {
        status = "okay";
};

&u2phy0_otg {
        status = "okay";
};

# USB2.0 PHY2
&u2phy2 {
        status = "okay";
};

&u2phy2_host {
        status = "okay";
};

# USB3.0/DP Combo PHY0
&usbdp_phy0 {
        status = "okay";
};

&usbdp_phy0_u3 {
        status = "okay";
};

# USB3.0/SATA/PCIe Combo PHY
&combphy2_psu {
        status = "okay";
};

USB2.0 PHY1USB2.0 PHY03USB3.0/DP Combo PHY1arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev09.dts中有使能:

# USB2.0 PHY1
&u2phy1 {
        status = "okay";
};

&u2phy1_otg {
        phy-supply = <&vcc5v0_host_30>;
        status = "okay";
};


# USB2.0 PHY3
&u2phy3 {
        status = "okay";
};

&u2phy3_host {
        phy-supply = <&vcc3v3_host_32>;
        status = "okay";
};

# USB3.0/DP Combo PHY1
&usbdp_phy1 {
        status = "okay";
};

&usbdp_phy1_u3 {
        status = "okay";
};
3.4 USB3.0 Type-C

NanoPC-T6开发板支持1个USB3.0 Type-C接口,对应的USB控制器为USB3.0 OTG0(DWC3/xHCI)、对应的USB PHYUSB3.0/DP Combo PHY0USB2 PHY0

因此对应的设备树配置,包括USB3.0 OTG0(DWC3/xHCI)控制器设备树配置和USB3.0/DP Combo PHY0USB2 PHY0设备树配置。

3.4.1 使能usbdrd3_0

通过dr_mode属性设置USB控制器的模式,一共有三种模式:otg(同时支持主机/设备)、host(主机)、peripheral(设备),这里配置为otg

arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev09.dts配置:

# USB3.0 OTG0(DWC3/xHCI)
&usbdrd3_0 {
        status = "okay";
};

&usbdrd_dwc3_0 {
        dr_mode = "otg";
        usb-role-switch;
        status = "okay";

        port {
                #address-cells = <1>;
                #size-cells = <0>;
                dwc3_0_role_switch: endpoint@0 {
                        reg = <0>;
                        remote-endpoint = <&usbc0_role_sw>;
                };
        };
};
3.4.2 使能u2phy0_otg

arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev09.dts配置:

# USB2.0 PHY0
&u2phy0 {
        status = "okay";
};

&u2phy0_otg {
        status = "okay";
};
3.4.3 使能usbdp_phy0_u3

arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev09.dts配置:

# USB3.0/DP Combo PHY0
&usbdp_phy0 {
        orientation-switch;
        rockchip,dp-lane-mux = <0 1 2 3 >;
        svid = <0xff01>;
	    # 根据硬件设计,配置属性"sbu1-dc-gpios"和"sbu2-dc-gpios"
        sbu1-dc-gpios = <&gpio4 RK_PA6 GPIO_ACTIVE_HIGH>;
        sbu2-dc-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>;
        status = "okay";

        port {
                #address-cells = <1>;
                #size-cells = <0>;
                usbdp_phy0_orientation_switch: endpoint@0 {
                        reg = <0>;
                        remote-endpoint = <&usbc0_orien_sw>;
                };

                usbdp_phy0_dp_altmode_mux: endpoint@1 {
                        reg = <1>;
                        remote-endpoint = <&dp_altmode_mux>;
                };
        };
};

&usbdp_phy0_u3 {
        status = "okay";
};
3.4.4 电源配置

USB3.0 Type-C电源VBUS5V0_TYPECSY6280AAC提供的,其输入端为VCC5V0_SYS。由TYPEC5V_PWREN_H(GPIO1_D2)引脚使能,高电平有效;

arch/arm64/boot/dts/rockchip/rk3588-nanopi6-common.dtsi配置vbus5v0_typec

vbus5v0_typec: vbus5v0-typec {
		compatible = "regulator-fixed";
		enable-active-high;
    	#  GPIO1_D2控制
		gpio = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>;
		pinctrl-names = "default";
		pinctrl-0 = <&typec5v_pwren>;
		regulator-name = "vbus5v0_typec";
		regulator-min-microvolt = <5000000>;
		regulator-max-microvolt = <5000000>;
		vin-supply = <&vcc5v0_usb>;
};
3.4.5 FUSB302配置

配置外置Type-C控制器芯片FUSB302,设备节点fusb302@22配置在arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev09.dts

&i2c6 {
        clock-frequency = <200000>;
        status = "okay";

        eeprom@53 {
                compatible = "microchip,24c02", "atmel,24c02";
                reg = <0x53>;
                #address-cells = <2>;
                #size-cells = <0>;
                pagesize = <16>;
                size = <256>;

                eui_48: eui-48@fa {
                        reg = <0xfa 0x06>;
                };
        };

        usbc0: fusb302@22 {
                compatible = "fcs,fusb302";
                reg = <0x22>;
                interrupt-parent = <&gpio0>;
                interrupts = ;
	            # 中断GPIO0_D3
                int-n-gpios = <&gpio0 RK_PD3 GPIO_ACTIVE_LOW>;
                pinctrl-names = "default";
                pinctrl-0 = <&usbc0_int>;
                vbus-supply = <&vbus5v0_typec>;
                status = "okay";

                ports {
                        #address-cells = <1>;
                        #size-cells = <0>;

                        port@0 {
                                reg = <0>;
                                usbc0_role_sw: endpoint@0 {
                                        remote-endpoint = <&dwc3_0_role_switch>;
                                };
                        };
                };
                usb_con: connector {
                        compatible = "usb-c-connector";
                        label = "USB-C";
                        data-role = "dual";
                        power-role = "dual";
                        try-power-role = "sink";
                        op-sink-microwatt = <1000000>;
                        sink-pdos =
                                ;
                        source-pdos =
                                ;

                        altmodes {
                                #address-cells = <1>;
                                #size-cells = <0>;

                                altmode@0 {
                                        reg = <0>;
                                        svid = <0xff01>;
                                        vdo = <0xffffffff>;
                                };
                        };

                        ports {
                                #address-cells = <1>;
                                #size-cells = <0>;

                                port@0 {
                                        reg = <0>;
                                        usbc0_orien_sw: endpoint {
                                                remote-endpoint = <&usbdp_phy0_orientation_switch>;
                                        };
                                };

                                port@1 {
                                        reg = <1>;
                                        dp_altmode_mux: endpoint {
                                                remote-endpoint = <&usbdp_phy0_dp_altmode_mux>;
                                        };
                                };
                        };
                };
        };
};
3.5 USB3.0 Type-A

NanoPC-T6开发板支持1个USB3.0 Type-A接口,对应的USB控制器为USB3.0 OTG1(DWC3/xHCI)、对应的USB PHYUSB3.0/DP Combo PHY1USB2 PHY1

因此对应的设备树配置,包括USB3.0 OTG1(DWC3/xHCI)控制器设备树配置和USB3.0/DP Combo PHY1USB2 PHY1设备树配置。

3.5.1 使能usbdrd3_0

通过dr_mode属性设置USB控制器的模式,这里配置为host

arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev09.dts中配置:

# USB3.0 OTG1(DWC3/xHCI)
&usbdrd3_1 {
        status = "okay";
};

# 如果配置dr_mode为otg,同时配置extcon = <&u2phy1>属性,才能支持软件切换Device/Host mode
&usbdrd_dwc3_1 {
        dr_mode = "host";
        snps,xhci-trb-ent-quirk;
        status = "okay";
};

注意:NanoPC-T6开发板大概率不支持USB3.0 Type-A作为Device mode使用,如果非要作为Device mode使用,可以尝试将工作模式dr_mode配置为otg

3.5.2 使能u2phy1_otg

USB3.0 Type-A工作为主机模式时,可以外接USB设备,比如鼠标,键盘,并为所连接的USB设备提供VBUS电源;因此需要配置phy-supply,用于控制VBUS输出5V

arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev09.dts配置:

# USB2.0 PHY1
&u2phy1 {
        status = "okay";
};

&u2phy1_otg {
        phy-supply = <&vcc5v0_host_30>;
        status = "okay";
};

注意:使用phy-supply,无法实现VBUS的动态开关。如果工作模式dr_mode配置为otg(支持Device/HOST),并且OTG独占GPIO,不与其它HOST共用,则应该配置为vbus-supply = <&vcc5v0_host_30>,才能实现VBUS动态开关.

3.5.3 使能usbdp_phy1_u3

arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev09.dts配置:

# USB3.0/DP Combo PHY1
&usbdp_phy1 {
        status = "okay";
};

&usbdp_phy1_u3 {
        status = "okay";
};
3.5.4 电源配置

USB3.0 Type-A电源VCC5V0_USB30_HOST2SY6280AAC提供的,其输入端为VCC5V0_SYS。由USB_HOST_PWREN_H(GPIO4_B0)引脚使能,,高电平有效;

arch/arm64/boot/dts/rockchip/rk3588-nanopi6-rev09.dts配置vcc5v0_host_30

vcc5v0_host_30: vcc5v0-host-30 {
		compatible = "regulator-fixed";
		enable-active-high;
    	# GPIO4_B0控制
		gpio = <&gpio4 RK_PB0 GPIO_ACTIVE_HIGH>;
		pinctrl-names = "default";
		pinctrl-0 = <&vcc5v0_host30_en>;
		regulator-name = "vcc5v0_host_30";
		regulator-min-microvolt = <5000000>;
		regulator-max-microvolt = <5000000>;
		vin-supply = <&vcc5v0_usb>;
};

四、调试接口

4.1 sysfs
4.1.1 USB设备

所有USB设备可以在/sys/bus/usb/devices下找到;

root@NanoPC-T6:~# ls -l /sys/bus/usb/devices
总用量 0
lrwxrwxrwx 1 root root 0 12月 18 23:56 1-0:1.0 -> ../../../devices/platform/usbdrd3_1/fc400000.usb/xhci-hcd.9.auto/usb1/1-0:1.0        # USB3.0 OTG1
lrwxrwxrwx 1 root root 0 12月 18 23:56 2-0:1.0 -> ../../../devices/platform/usbdrd3_1/fc400000.usb/xhci-hcd.9.auto/usb2/2-0:1.0        # USB3.0 OTG1
lrwxrwxrwx 1 root root 0 12月 18 23:56 3-0:1.0 -> ../../../devices/platform/fc800000.usb/usb3/3-0:1.0 # USB2.0 HOST0 EHCI
lrwxrwxrwx 1 root root 0 12月 18 23:56 4-0:1.0 -> ../../../devices/platform/fc840000.usb/usb4/4-0:1.0 # USB2.0 HOST0 OHCI
lrwxrwxrwx 1 root root 0 12月 18 23:56 5-0:1.0 -> ../../../devices/platform/fc880000.usb/usb5/5-0:1.0 # USB2.0 HOST1 EHCI
lrwxrwxrwx 1 root root 0 12月 18 23:56 6-0:1.0 -> ../../../devices/platform/fc8c0000.usb/usb6/6-0:1.0 # USB2.0 HOST1 OHCI
lrwxrwxrwx 1 root root 0 12月 18 23:56 usb1 -> ../../../devices/platform/usbdrd3_1/fc400000.usb/xhci-hcd.9.auto/usb1
lrwxrwxrwx 1 root root 0 12月 18 23:56 usb2 -> ../../../devices/platform/usbdrd3_1/fc400000.usb/xhci-hcd.9.auto/usb2
lrwxrwxrwx 1 root root 0 12月 18 23:56 usb3 -> ../../../devices/platform/fc800000.usb/usb3
lrwxrwxrwx 1 root root 0 12月 18 23:56 usb4 -> ../../../devices/platform/fc840000.usb/usb4
lrwxrwxrwx 1 root root 0 12月 18 23:56 usb5 -> ../../../devices/platform/fc880000.usb/usb5
lrwxrwxrwx 1 root root 0 12月 18 23:56 usb6 -> ../../../devices/platform/fc8c0000.usb/usb6

如上图所示,可以看到大量的USB设备。取名规则如下:

bus-port[.port]:configuration.interface

其中:

  • bus:表示USB控制器所连接的总线编号;从1开始编号;
  • port:表示总线上的硬件端口号;从0开始编号;比如1-0是根hub自身信息,当hub上有插入设备时,就会出现1-1了。
  • port:如果总线上的硬件端口连接的设备是一个HUB,那么该port表示连接在hub上的硬件端口号;从1开始编号;
  • configuration:表示设备的配置值;从1开始编号;
  • interface:表示设备的接口号;从0开始编号;

比如1-1:1.1具有以下含义:

  • 1-1:表示连接到第一个USB控制器的编号为1的硬件端口;
  • 1.1:表示设备的第一个配置(configuration)编号为1接口(interface)。

7-1.2:1.0具有以下含义:

  • 7-1.2:表示连接到第7个USB控制器的编号为1的硬件端口连接了一个hubhub编号为2的硬件端口上连接了一个设备;
  • 1.0:表示设备的第一个配置(configuration)编号为0接口(interface)。
4.1.2 USB设备信息

由于当前开发板的USB接口没有介入任何设备,因此看到都是USB控制器上连接的root hub

root@NanoPC-T6:~# cd /sys/bus/usb/devices
root@NanoPC-T6:/sys/bus/usb/devices# ls
1-0:1.0  2-0:1.0  3-0:1.0  4-0:1.0  5-0:1.0  6-0:1.0  usb1  usb2  usb3  usb4  usb5  usb6

root@NanoPC-T6:/sys/bus/usb/devices# lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub

接着我们向开发板USB3.0 Type-A接口插入一个鼠标,再次查看:

root@NanoPC-T6:/sys/bus/usb/devices# ls
1-0:1.0  1-1  1-1:1.0  1-1:1.1  1-1:1.2  2-0:1.0  3-0:1.0  4-0:1.0  5-0:1.0  6-0:1.0  usb1  usb2  usb3  usb4  usb5  usb6

可以看到多出了目录1-1 1-1:1.0 1-1:1.1 1-1:1.2

lrwxrwxrwx 1 root root 0 12月 23 12:05 1-1 -> ../../../devices/platform/usbdrd3_1/fc400000.usb/xhci-hcd.9.auto/usb1/1-1
lrwxrwxrwx 1 root root 0 12月 23 12:05 1-1:1.0 -> ../../../devices/platform/usbdrd3_1/fc400000.usb/xhci-hcd.9.auto/usb1/1-1/1-1:1.0
lrwxrwxrwx 1 root root 0 12月 23 12:05 1-1:1.1 -> ../../../devices/platform/usbdrd3_1/fc400000.usb/xhci-hcd.9.auto/usb1/1-1/1-1:1.1
lrwxrwxrwx 1 root root 0 12月 23 12:05 1-1:1.2 -> ../../../devices/platform/usbdrd3_1/fc400000.usb/xhci-hcd.9.auto/usb1/1-1/1-1:1.2

实际上后面三个都是链接文件都是指向1-1目录下的子文件。1-1表示连接到第一个USB控制器的编号为1的硬件端口;

  • 1-1:1.0:表示设备的第一个配置(configuration)编号为0接口(interface);
  • 1-1:1.1:表示设备的第一个配置(configuration)编号为1接口(interface);
  • 1-1:1.2:表示设备的第一个配置(configuration)编号为2接口(interface);

我们查看一下USB鼠标的信息:

root@NanoPC-T6:/sys/bus/usb/devices# cat 1-1/idProduct
c52b
root@NanoPC-T6:/sys/bus/usb/devices# cat 1-1/idVendor
046d
root@NanoPC-T6:/sys/bus/usb/devices# cat 1-1/product
USB Receiver
root@NanoPC-T6:/sys/bus/usb/devices# cat 1-1/manufacturer
Logitech

实际上这个信息在内核日志也是可以看到的:

[389322.004486] usb 1-1: new full-speed USB device number 9 using xhci-hcd
[389322.147736] usb 1-1: New USB device found, idVendor=046d, idProduct=c52b, bcdDevice=24.11
[389322.147753] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[389322.147762] usb 1-1: Product: USB Receiver
[389322.147769] usb 1-1: Manufacturer: Logitech
[389322.189271] logitech-djreceiver 0003:046D:C52B.0015: hiddev96,hidraw0: USB HID v1.11 Device [Logitech USB Receiver] on usb-xhci-hcd.9.auto-1/input2
[389322.311793] input: Logitech M545/M546 as /devices/platform/usbdrd3_1/fc400000.usb/xhci-hcd.9.auto/usb1/1-1/1-1:1.2/0003:046D:C52B.0015/0003:046D:4052.0016/input/input28
[389322.312977] logitech-hidpp-device 0003:046D:4052.0016: input,hidraw1: USB HID v1.11 Mouse [Logitech M545/M546] on usb-xhci-hcd.9.auto-1/input2:1
[389343.419592] logitech-hidpp-device 0003:046D:4052.0016: HID++ 4.5 device connected.

USB鼠标工作在全速模式下,xHCI控制器,USB1.1通信协议,使用的USB总线编号为1,设备编号为9。

4.2 debugfs

USB调试信息位于/sys/kernel/debug/usb

root@NanoPC-T6:~# ls -l /sys/kernel/debug/usb/
总用量 0
-r--r--r--  1 root root 0  1月  1  1970 devices
drwxr-xr-x  4 root root 0  1月  1  1970 ehci
drwxr-xr-x 18 root root 0  1月  1  1970 fc000000.usb
drwxr-xr-x  2 root root 0  1月  1  1970 fc400000.usb
drwxr-xr-x  2 root root 0 12月 18 23:56 fusb302-6-0022
drwxr-xr-x  4 root root 0  1月  1  1970 ohci
drwxr-xr-x  2 root root 0 12月 18 23:56 tcpm-6-0022
drwxr-xr-x  3 root root 0  1月  1  1970 xhci

其中:

  • devices:该文件列出了当前系统中已连接的USB设备的详细信息;
  • ehci:该目录包含EHCI主机控制器接口的调试信息;
  • fc000000.usb:该目录包含与fc000000.usb控制器相关的调试信息,即USB3.0 OTG0控制器;
  • fc400000.usb:该目录包含与fe900000.usb控制器相关的调试信息,即USB3.0 OTG1控制器;
  • fusb302-6-0022:该目录包含与fusb302-6-0022设备相关的调试信息,6为I2C总线编号,0022为I2C设备地址;
  • ohci:该目录包含OHCI主机控制器接口的调试信息;
  • tcpm-6-0022:该目录包含与tcpm-6-0022设备相关的调试信息,4为I2C总线编号,0022为I2C设备地址;
  • xhci:该目录包含XHCI主机控制器的调试信息;
4.2.1 查看USB3.0 OTG0工作模式

查看USB3.0 OTG0(DWC3/xHCI)控制器工作模式,USB3.0 OTG0(DWC3/xHCI)控制器对应设备节点usbdrd3_0: usb@fc000000

root@NanoPC-T6:~#  ls -l /sys/kernel/debug/usb/fc000000.usb/
总用量 0
drwxr-xr-x 2 root root 0 12月 18 23:56 ep0in
drwxr-xr-x 2 root root 0 12月 18 23:56 ep0out
drwxr-xr-x 2 root root 0 12月 18 23:56 ep1in
drwxr-xr-x 2 root root 0 12月 18 23:56 ep1out
drwxr-xr-x 2 root root 0 12月 18 23:56 ep2in
drwxr-xr-x 2 root root 0 12月 18 23:56 ep2out
drwxr-xr-x 2 root root 0 12月 18 23:56 ep3in
drwxr-xr-x 2 root root 0 12月 18 23:56 ep3out
drwxr-xr-x 2 root root 0 12月 18 23:56 ep4in
drwxr-xr-x 2 root root 0 12月 18 23:56 ep4out
drwxr-xr-x 2 root root 0 12月 18 23:56 ep5in
drwxr-xr-x 2 root root 0 12月 18 23:56 ep5out
drwxr-xr-x 2 root root 0 12月 18 23:56 ep6in
drwxr-xr-x 2 root root 0 12月 18 23:56 ep7in
drwxr-xr-x 2 root root 0 12月 18 23:56 ep8in
drwxr-xr-x 2 root root 0 12月 18 23:56 ep9in
-rw-r--r-- 1 root root 0  1月  1  1970 link_state
-rw-r--r-- 1 root root 0  1月  1  1970 lsp_dump
-rw-r--r-- 1 root root 0  1月  1  1970 mode
-r--r--r-- 1 root root 0  1月  1  1970 regdump
-rw-r--r-- 1 root root 0  1月  1  1970 testmode

其中:

  • link_state:打印DWC3的链路状态;
  • regdump:打印DWC3控制器的寄存器状态信息;
  • mode:打印DWC3的工作模式;
  • testmode:设置DWC3HighSpeed的测试模式;

此外,DWC3控制器驱动还实现了基于内核trace框架的tracepoint,支持动态使能并保存DWC3驱动关键信息。

(1) 设备模式

我们通过Type-C连接线将USB3.0 Type-C接口与PC连接在一起,我们可以查看USB3.0 OTG0控制器的工作模式:

root@NanoPC-T6:~#  cat /sys/kernel/debug/usb/fc000000.usb/mode
device

可以看到USB3.0 OTG0控制器工作在Device(设备)模式。

(2) 主机模式

如果我们将Type-C接口的U盘连接到USB3.0 Type-C接口,可以看到内核日志如下:

[348278.750101] phy phy-fd5d0000.syscon:[email protected]: illegal mode
[348278.750125] xhci-hcd xhci-hcd.13.auto: xHCI Host Controller
[348278.750143] xhci-hcd xhci-hcd.13.auto: new USB bus registered, assigned bus number 7
[348278.750245] xhci-hcd xhci-hcd.13.auto: hcc params 0x0220fe64 hci version 0x110 quirks 0x0000202002010010
[348278.750273] xhci-hcd xhci-hcd.13.auto: irq 90, io mem 0xfc000000
[348278.750376] xhci-hcd xhci-hcd.13.auto: xHCI Host Controller
[348278.750387] xhci-hcd xhci-hcd.13.auto: new USB bus registered, assigned bus number 8
[348278.750398] xhci-hcd xhci-hcd.13.auto: Host supports USB 3.0 SuperSpeed
[348278.750499] usb usb7: New USB device found, idVendor=1d6b, idProduct=0002, bcdDevice= 6.01
[348278.750509] usb usb7: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[348278.750517] usb usb7: Product: xHCI Host Controller
[348278.750524] usb usb7: Manufacturer: Linux 6.1.25 xhci-hcd
[348278.750530] usb usb7: SerialNumber: xhci-hcd.13.auto
[348278.750822] hub 7-0:1.0: USB hub found
[348278.750848] hub 7-0:1.0: 1 port detected
[348278.751081] usb usb8: We don't know the algorithms for LPM for this host, disabling LPM.
[348278.751155] usb usb8: New USB device found, idVendor=1d6b, idProduct=0003, bcdDevice= 6.01
[348278.751165] usb usb8: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[348278.751173] usb usb8: Product: xHCI Host Controller
[348278.751179] usb usb8: Manufacturer: Linux 6.1.25 xhci-hcd
[348278.751186] usb usb8: SerialNumber: xhci-hcd.13.auto
[348278.751444] hub 8-0:1.0: USB hub found
[348278.751467] hub 8-0:1.0: 1 port detected
[348278.999777] usb 7-1: new high-speed USB device number 2 using xhci-hcd
[348279.140469] usb 7-1: New USB device found, idVendor=14cd, idProduct=1212, bcdDevice= 1.00
[348279.140494] usb 7-1: New USB device strings: Mfr=1, Product=3, SerialNumber=2
[348279.140502] usb 7-1: Product: Mass Storage Device
[348279.140509] usb 7-1: Manufacturer: Generic
[348279.140516] usb 7-1: SerialNumber: 121220160204
[348279.141207] usb-storage 7-1:1.0: USB Mass Storage device detected
[348279.141451] scsi host0: usb-storage 7-1:1.0
[348280.146932] scsi 0:0:0:0: Direct-Access     Mass     Storage Device   1.00 PQ: 0 ANSI: 0 CCS
[348280.147312] sd 0:0:0:0: Attached scsi generic sg0 type 0
[348280.301906] sd 0:0:0:0: [sda] 30277632 512-byte logical blocks: (15.5 GB/14.4 GiB)
[348280.302047] sd 0:0:0:0: [sda] Write Protect is off
[348280.302057] sd 0:0:0:0: [sda] Mode Sense: 03 00 00 00
[348280.302184] sd 0:0:0:0: [sda] No Caching mode page found
[348280.302193] sd 0:0:0:0: [sda] Assuming drive cache: write through
[348280.308888]  sda: sda1 sda2 sda3 sda4 sda5 sda6 sda7 sda8 sda9
[348280.309574] sd 0:0:0:0: [sda] Attached SCSI removable disk

同时USB3.0 OTG0控制器工作在Host(主机)模式;

root@NanoPC-T6:~#  cat /sys/kernel/debug/usb/fc000000.usb/mode
host
4.2.2 查看USB3.0 OTG1工作模式

查看USB3.0 OTG1(DWC3/xHCI)控制器工作模式,USB3.0 OTG1(DWC3/xHCI)控制器对应设备节点usbdrd3_1: usb@fc400000

root@NanoPC-T6:~# cat /sys/kernel/debug/usb/fc400000.usb/mode
host

可以看到USB3.0 OTG1控制器工作在Host(主机)模式。

4.2.3 查看xhci
root@NanoPC-T6:~# ls -l /sys/kernel/debug/usb/xhci/
总用量 0
drwxr-xr-x 6 root root 0  1月  1  1970 xhci-hcd.9.auto
root@NanoPC-T6:~# ls -l /sys/kernel/debug/usb/xhci/xhci-hcd.9.auto/
总用量 0
drwxr-xr-x 2 root root 0  1月  1  1970 command-ring
drwxr-xr-x 3 root root 0 12月 23 00:57 devices
drwxr-xr-x 2 root root 0  1月  1  1970 event-ring
drwxr-xr-x 4 root root 0  1月  1  1970 ports
-r--r--r-- 1 root root 0  1月  1  1970 reg-cap
-r--r--r-- 1 root root 0  1月  1  1970 reg-ext-legsup:00
-r--r--r-- 1 root root 0  1月  1  1970 reg-ext-protocol:00
-r--r--r-- 1 root root 0  1月  1  1970 reg-ext-protocol:01
-r--r--r-- 1 root root 0  1月  1  1970 reg-op
-r--r--r-- 1 root root 0  1月  1  1970 reg-runtime
4.2.4 查看ehci
root@NanoPC-T6:~# ls -l /sys/kernel/debug/usb/ehci/
总用量 0
drwxr-xr-x 2 root root 0  1月  1  1970 fc800000.usb
drwxr-xr-x 2 root root 0  1月  1  1970 fc880000.usb
root@NanoPC-T6:~# ls -l /sys/kernel/debug/usb/ehci/fc800000.usb/
总用量 0
-r--r--r-- 1 root root 0  1月  1  1970 async
-r--r--r-- 1 root root 0  1月  1  1970 bandwidth
-r--r--r-- 1 root root 0  1月  1  1970 periodic
-r--r--r-- 1 root root 0  1月  1  1970 registers
4.2.5 查看fusb302-6-0022
root@NanoPC-T6:~# ls -l /sys/kernel/debug/usb/fusb302-6-0022/
总用量 0
-r--r--r-- 1 root root 0 12月 18 23:56 log

该文件会记录USB3.0 Type-C接口设备插拔时以及角色切换的信息,以USB3.0 Type-C接口有USB鼠标接入的日志为例;

root@NanoPC-T6:~# cat /sys/kernel/debug/usb/fusb302-6-0022/log  
[392786.091210] IRQ: 0x21, a: 0x40, b: 0x00, status0: 0x01
[392786.091216] IRQ: TOGDONE
[392786.091810] get_src_cc_status switches: 0x44
[392786.092295] get_src_cc_status rd_mda status0: 0x1
[392786.092778] get_src_cc_status ra_mda status0: 0x21
[392786.094659] get_src_cc_status switches: 0x88
[392786.095143] get_src_cc_status rd_mda status0: 0x23
[392786.096222] detected cc1=Rd, cc2=Open
[392786.096231] cc1=Rd, cc2=Open
[392786.097099] IRQ: 0x21, a: 0x00, b: 0x00, status0: 0x01
[392786.097103] IRQ: COMP_CHNG, comp=false
[392786.296268] cc := Rd
[392786.299776] IRQ: 0x01, a: 0x00, b: 0x00, status0: 0x00
[392786.299779] IRQ: BC_LVL, handler pending
[392786.331880] BC_LVL handler, status0=0x00
[392786.398930] cc := Rp-1.5
[392786.504005] start drp toggling
[392786.553159] IRQ: 0x01, a: 0x40, b: 0x00, status0: 0x01
[392786.553166] IRQ: TOGDONE
[392786.553760] get_src_cc_status switches: 0x44
[392786.554244] get_src_cc_status rd_mda status0: 0x1
[392786.554728] get_src_cc_status ra_mda status0: 0x21
[392786.556609] get_src_cc_status switches: 0x88
[392786.557092] get_src_cc_status rd_mda status0: 0x23
[392786.558168] detected cc1=Rd, cc2=Open    # 检测到对方是Rd下拉,因此USB3.0 Type-C接口作为供电方
[392786.558176] cc1=Rd, cc2=Open
[392786.559045] IRQ: 0x20, a: 0x00, b: 0x00, status0: 0x01
[392786.559048] IRQ: COMP_CHNG, comp=false
[392786.758666] pd header := Source, Host     # 工作为主机模式
[392786.761053] pd := on
[392786.761069] vbus := On     
[392786.761071] charge is already Off
[392786.762222] IRQ: 0x80, a: 0x00, b: 0x00, status0: 0x81
[392786.762226] IRQ: VBUS_OK, vbus=On         # VBUS供电开启,为连接的USB设备提供VBUS电源 
[392786.762248] cc := Rp-1.5
[392786.766246] sending PD message header: 11a1
[392786.766249] sending PD message len: 4
[392786.773617] IRQ: 0x41, a: 0x10, b: 0x00, status0: 0x82
[392786.773621] IRQ: PD retry failed
......

USB鼠标从USB3.0 Type-C接口移除:

root@NanoPC-T6:~# cat /sys/kernel/debug/usb/fusb302-6-0022/log  
[392791.999035] cc := Rp-1.5
[393000.156208] IRQ: 0x21, a: 0x00, b: 0x00, status0: 0xa3
[393000.156213] IRQ: COMP_CHNG, comp=true
[393000.156227] cc1=Open, cc2=Open
[393000.158609] pd := off
[393000.158623] vbus := Off
[393000.158625] charge is already Off
[393000.158627] vconn is already Off
[393000.159121] pd header := Source, Host
[393000.160014] IRQ: 0x80, a: 0x00, b: 0x00, status0: 0x23
[393000.160018] IRQ: VBUS_OK, vbus=Off   # VBUS供电关闭
[393000.162340] start drp toggling

如果USB3.0 Type-C接口连接到PC

root@NanoPC-T6:~# cat /sys/kernel/debug/usb/fusb302-6-0022/log
[394208.588702] IRQ: 0xa0, a: 0x00, b: 0x00, status0: 0x83
[394208.588708] IRQ: VBUS_OK, vbus=On
[394208.639880] IRQ: 0x01, a: 0x40, b: 0x00, status0: 0x81
[394208.639883] IRQ: TOGDONE
[394208.642732] detected cc1=Rp-def, cc2=Open # 检测到对方是Rp上拉,因此USB3.0 Type-C接口作为耗电方
[394208.642741] cc1=Rp-def, cc2=Open
[394208.843243] pd header := Sink, Device     # 工作为设备模式
[394208.843304] vbus is already Off           # VBUS供电关闭
[394208.845588] pd := on
[394209.157028] IRQ: 0x41, a: 0x08, b: 0x00, status0: 0x81
[394209.157033] IRQ: BC_LVL, handler pending
[394209.157035] IRQ: PD hardreset sent
[394209.159680] pd := off
[394209.160553] IRQ: 0x41, a: 0x00, b: 0x00, status0: 0x81
[394209.160556] IRQ: BC_LVL, handler pending
[394209.160564] vconn is already Off
[394209.161001] pd header := Sink, Device
[394209.193529] BC_LVL handler, status0=0x81
[394209.811430] pd header := Sink, Device
[394209.813727] pd := on
[394210.125174] IRQ: 0x41, a: 0x08, b: 0x00, status0: 0x81
[394210.125178] IRQ: BC_LVL, handler pending
[394210.125180] IRQ: PD hardreset sent
[394210.127826] pd := off
[394210.127834] vconn is already Off
[394210.128705] IRQ: 0x41, a: 0x00, b: 0x00, status0: 0x81
[394210.128709] IRQ: BC_LVL, handler pending
[394210.129098] pd header := Sink, Device
[394210.160249] BC_LVL handler, status0=0x81

Type-C连接线从USB3.0 Type-C接口移除:

root@NanoPC-T6:~# cat /sys/kernel/debug/usb/fusb302-6-0022/log
[394417.434921] IRQ: 0x01, a: 0x00, b: 0x00, status0: 0x80
[394417.434926] IRQ: BC_LVL, handler pending
[394417.436373] IRQ: 0x80, a: 0x00, b: 0x00, status0: 0x00
[394417.436377] IRQ: VBUS_OK, vbus=Off
[394417.438761] pd := off
[394417.438763] vbus is already Off
[394417.438765] vconn is already Off
[394417.439232] pd header := Sink, Device
[394417.441507] start drp toggling
[394417.466218] BC_LVL interrupt is turned off, abort
4.2.6 查看tcpm-6-0022
root@NanoPC-T6:~# ls -l /sys/kernel/debug/usb/tcpm-6-0022
总用量 0
-r--r--r-- 1 root root 0 12月 18 23:56 log
root@NanoPC-T6:~# cat /sys/kernel/debug/usb/tcpm-6-0022/log
[394482.036794] CC1: 3 -> 0, CC2: 0 -> 2 [state TOGGLING, polarity 0, connected]
[394482.036799] state change TOGGLING -> SRC_ATTACH_WAIT [rev3 NONE_AMS]
[394482.036803] pending state change SRC_ATTACH_WAIT -> SNK_TRY @ 200 ms [rev3 NONE_AMS]
[394482.236822] state change SRC_ATTACH_WAIT -> SNK_TRY [delayed 200 ms]
[394482.236824] cc:=2
[394482.239467] pending state change SNK_TRY -> SNK_TRY_WAIT @ 100 ms [rev3 NONE_AMS]
[394482.339481] state change SNK_TRY -> SNK_TRY_WAIT [delayed 100 ms]
[394482.339483] state change SNK_TRY_WAIT -> SRC_TRYWAIT [rev3 NONE_AMS]
[394482.339486] cc:=4
[394482.342281] pending state change SRC_TRYWAIT -> SRC_TRYWAIT_UNATTACHED @ 100 ms [rev3 NONE_AMS]
[394482.442295] state change SRC_TRYWAIT -> SRC_TRYWAIT_UNATTACHED [delayed 100 ms]
[394482.442297] state change SRC_TRYWAIT_UNATTACHED -> SNK_UNATTACHED [rev3 NONE_AMS]
[394482.442300] Start toggling
[394482.444558] state change SNK_UNATTACHED -> TOGGLING [rev3 NONE_AMS]
[394482.501840] CC1: 0 -> 0, CC2: 2 -> 2 [state TOGGLING, polarity 0, connected]
[394482.501843] state change TOGGLING -> SRC_ATTACH_WAIT [rev3 NONE_AMS]
[394482.501846] pending state change SRC_ATTACH_WAIT -> SRC_ATTACHED @ 200 ms [rev3 NONE_AMS]
[394482.701864] state change SRC_ATTACH_WAIT -> SRC_ATTACHED [delayed 200 ms]
[394482.701866] polarity 1
[394482.701868] Requesting mux state 1, usb-role 1, orientation 2
[394482.704678] vbus:=1 charge=0
[394482.704693] pending state change SRC_ATTACHED -> SRC_UNATTACHED @ 480 ms [rev3 NONE_AMS]
[394482.705850] VBUS on
[394482.705852] state change SRC_ATTACHED -> SRC_STARTUP [rev3 NONE_AMS]
[394482.705888] AMS POWER_NEGOTIATION start
[394482.705890] cc:=4
[394482.708702] state change SRC_STARTUP -> AMS_START [rev3 POWER_NEGOTIATION]
[394482.708707] state change AMS_START -> SRC_SEND_CAPABILITIES [rev3 POWER_NEGOTIATION]
[394482.708710] PD TX, header: 0x11a1
[394482.717265] PD TX complete, status: 2
[394482.717274] pending state change SRC_SEND_CAPABILITIES -> SRC_SEND_CAPABILITIES @ 150 ms [rev3 POWER_NEGOTIATION]
......
4.3 切换USB3.0 OTG工作模式

我们使用的开发板USB3.0 Type-C PHY0USB2.0 OTG PHY0物理接口被设计为USB3.0 Type-C,并且外置了Type-C控制器芯片(FUSB302)支持软件自动切换Deivice/Host mode

USB3.0 Type-C PHY1USB2.0 OTG PHY1物理接口被设计为USB3.0 Type-A,并且TYPEC1_USB20_VBUSDET引脚悬空处理,USB3.0 Type-A接口只能作为HOST mode使用。

RK3588支持通过软件方法,强制设置USB OTG控制器切换到Host mode或者Device mode,而不受USB硬件电路的OTG ID电平或者 Type-C接口的影响。具体有如下两种方式:

  • 方式1依赖于USB dts的正确配置,只能用于非Type-C接口的硬件电路设计;
  • 方式2没有限制。因此,在不确定软硬件是否正确适配时,推荐优先使用方式2。
4.3.1 方式一

查看工作模式:

root@NanoPC-T6:~# cat /sys/devices/platform/fd5d0000.syscon/fd5d0000.syscon:usb2-phy@0/otg_mode
otg
root@NanoPC-T6:~# cat /sys/devices/platform/fd5d4000.syscon/fd5d4000.syscon:usb2-phy@4000/otg_mode
host

更改USB3.0 OTG0为主机模式;

root@NanoPC-T6:~# echo host > /sys/devices/platform/fd5d0000.syscon/fd5d0000.syscon:usb2-phy@0/otg_mode

更改USB3.0 OTG0为设备模式;

root@NanoPC-T6:~# echo peripheral > /sys/devices/platform/fd5d0000.syscon/fd5d0000.syscon:usb2-phy@0/otg_mode

注意:对于Type-C接口硬件电路设置不会生效,Type-C控制器(Fusb302)会自动检测连接的USB设备,软件自行将USB3.0 OTG0控制器配置为Host(主机)、Device(从机)或双重角色。

4.3.2 方式二

更改USB3.0 OTG0为主机模式:

# Force host mode  
root@NanoPC-T6:~# echo host > /sys/kernel/debug/usb/fc000000.usb/mode

更改USB3.0 OTG0为设备模式:

# Force device mode 
root@NanoPC-T6:~# echo device > /sys/kernel/debug/usb/fc000000.usb/mode

当然,我们也可以尝试更改USB3.0 OTG1为主机模式:

# Force host mode 
root@NanoPC-T6:~# echo host > /sys/kernel/debug/usb/fc400000.usb/mode

更改USB3.0 OTG1为设备模式:

root@NanoPC-T6:~# echo device > /sys/kernel/debug/usb/fc400000.usb/mode

该设置会强制将USB3.0 OTG0控制器配置为指定的工作模式。比如USB3.0 Type-C接口当前连接着鼠标设备并且工作为主机模式,如果将其设置为设备模式,鼠标将无法工作。

4.4 作为主机模式测试

无论是开发板上的USB3.0 Type-C接口、还是USB3.0 Type-A接口作为主机模式测试都是很简单,将USB3.0 OTG工作模式切换为主机模式,然后在相应USB接口插入鼠标设备,看看鼠标设备能不能正常工作就可以了;

root@NanoPC-T6:~# echo host > /sys/kernel/debug/usb/fc000000.usb/mode   # USB3.0 Type-C接口
root@NanoPC-T6:~# echo host > /sys/kernel/debug/usb/fc400000.usb/mode   # USB3.0 Type-A接口

很显然,测试结果鼠标无论插到哪个USB接口都可以正常工作。

4.5 作为设备模式测试

在进行模拟之前,我们需要将/bin/usbdevice文件移动到/opt/hid目录下,这个是官方提供的用于模拟各种usb设备的脚本,系统系统会自动执行,默认还是将开发板模拟成adb终端(通过/etc/profile.d/usbdevice.sh配置的)。

这里我们不使用官方提供的脚本,主要是这个脚本支持模拟的设备种类比较多,并且代码比较复杂,有兴趣可以自己研究。

root@NanoPC-T6:/# mkdir /opt/hid
root@NanoPC-T6:/# cd /opt/hid
root@NanoPC-T6:/opt/hid# mv /bin/usbdevice /opt/hid

接下来我们会通过USB3.0 Type-C接口进行模拟触摸屏设备,如果想模拟鼠标,键盘可以参考文章:《四、 模拟USB设备》。

4.5.1 hid_touch脚本

下面我们创建一个触摸屏设备,然后编写hid_touch.sh脚本,文件存放在开发板debian系统/opt/hid路径下;

#!/bin/bash

gadget=g2

do_start(){ 
    has_mount=$(mount -l | grep /sys/kernel/config)
    if [[ -z  $has_mount ]];then
        mount -t configfs none /sys/kernel/config
    fi
    cd /sys/kernel/config/usb_gadget

    # 当我们创建完这个文件夹之后,系统自动的在这个文件夹中创建usb相关的内容 ,这些内容需要由创建者自己填写
    if [[ ! -d ${gadget} ]]; then
		mkdir ${gadget}
	fi
    cd ${gadget}

    #设置USB协议版本USB2.0
    echo 0x0200 > bcdUSB

    #定义产品的VendorID和ProductID
    echo "0x0525"  > idVendor
    echo "0xa4ac" > idProduct

    #实例化"英语"ID:
    mkdir strings/0x409

    #将开发商、产品和序列号字符串写入内核
    echo "76543210" > strings/0x409/serialnumber
    echo "mkelehk"  > strings/0x409/manufacturer
    echo "touch_screen"  > strings/0x409/product

    #创建一个USB配置实例
    if [[ ! -d configs/c.1 ]]; then
        mkdir configs/c.1
    fi

    #定义配置描述符使用的字符串
	if [[ ! -d configs/c.1/strings/0x409 ]]; then
		mkdir configs/c.1/strings/0x409
	fi   

    echo "hid" > configs/c.1/strings/0x409/configuration

    #创建功能实例,需要注意的是,一个功能如果有多个实例的话,扩展名必须用数字编号:
    mkdir functions/hid.0   

    #配置hid描述符(根据hid协议或者g_hid.ko对于的源码hid.c的说明)
    echo 0 > functions/hid.0/subclass  
    echo 0 > functions/hid.0/protocol   
    echo 5 > functions/hid.0/report_length  #标识该hid设备每次发送的报表长度为5字节
    echo -ne \\x05\\x01\\x09\\x02\\xa1\\x01\\x09\\x01\\xa1\\x00\\x05\\x09\\x19\\x01\\x29\\x05\\x15\\x00\\x25\\x01\\x95\\x05\\x75\\x01\\x81\\x02\\x95\\x01\\x75\\x03\\x81\\x01\\x05\\x01\\x09\\x30\\x09\\x31\\x15\\x00\\x26\\xff\\x7f\\x35\\x00\\x46\\xff\\x7f\\x75\\x10\\x95\\x02\\x81\\x02\\xc0\\xc0 > functions/hid.0/report_desc

    #捆绑功能实例到配置config.1
    ln -s functions/hid.0 configs/c.1
	
	#配置USB3.0 OTG0的工作模式为Device(设备):
	echo device > /sys/kernel/debug/usb/fc000000.usb/mode

    echo "sleep 3s"
    sleep 3s

    #将gadget驱动注册到UDC上,插上USB线到电脑上,电脑就会枚举USB设备。  
    echo fc000000.usb > UDC     # 可以通过 ls /sys/class/udc/命令查看USB设备控制器
}

do_stop() {
    cd /sys/kernel/config/usb_gadget/${gadaget}
    echo "" > UDC
}

case $1 in
    start)
        echo "Start hid gadget "
        do_start 
        ;;
    stop)
        echo "Stop hid gadget"
        do_stop
        ;;
    *)
        echo "Usage: $0 (stop | start)"
        ;;
esac

对于触摸屏设备,我们配置:

  • subclass:接口子类,配置为0;
  • protocol:接口协议,配置为0;
  • report_length:报告长度配置为5,触摸屏与鼠标的不同点是鼠标的上报值是相对坐标,触摸屏是绝对坐标,鼠标x、y轴分别需要一个字节,而触摸屏一般为16bit即两个字节;

在开发板debian系统运行命令模拟触摸屏:

root@NanoPC-T6:/opt/hid# echo device > /sys/kernel/debug/usb/fc000000.usb/mode
root@NanoPC-T6:/opt/hid# ls /sys/kernel/config/usb_gadget/
root@NanoPC-T6:/opt/hid# bash hid_touch.sh start
Start hid gadget
sleep 3s
root@NanoPC-T6:/opt/hid# ls /sys/kernel/config/usb_gadget/
g2
root@NanoPC-T6:/opt/hid# ls /sys/kernel/config/usb_gadget/g2
UDC           bDeviceProtocol  bMaxPacketSize0  bcdUSB   functions  idVendor  strings
bDeviceClass  bDeviceSubClass  bcdDevice        configs  idProduct  os_desc

此时会在/dev目录下生成了设备节点/dev/hidg0

root@NanoPC-T6:/opt/hid# ls  -l /dev/hidg*
crw------- 1 root root 511, 0 12月 23 13:54 /dev/hidg0

如果需卸载触摸屏,执行如下命令:

root@NanoPC-T6:/opt/hid# bash hid_touch.sh stop

如果卸载不能生效,尝试重启系统。

4.5.2 编写应用程序

然后我们通过设备节点/dev/hidg0、就可以模拟触摸屏实现与PC的通信。

编写测试应用程序hid_touch_control.c,文件存放在debian开发板/opt/hid路径下;

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

/**
 * 触摸屏每次发送5字节报告
 * report[0]的D0就是左键,D1就是右键,D2就是中键
 * report[1]为X轴低字节
 * report[2]为X轴高字节
 * report[3]为Y轴低字节
 * report[4]为Y轴高字节,
*/

/**
 * @brief 将焦点移动到指定位置
 * 
 * @param fd 文件描述符
 * @param x x轴坐标
 * @param y y轴坐标
 */
void move_To(int fd ,int x, int y)
{
    char report[5]={0,0,0,0,0};
    report[0] = 0x00;
    report[1] = x & 0xFF;
    report[2] = (x >> 8) & 0xFF;
    report[3] = y & 0xFF;
    report[4] = (y >> 8) & 0xFF;

    // 写入失败
    if (write(fd, report, 5) != 5) {
        perror("move_To error");
        return;
    }
    usleep(50000);
}


/**
 * @brief 函数功能:画线段的函数。
 * 
  *@param fd 文件描述符
 * @param x x轴坐标
 * @param y y轴坐标
 */
void line_to(int fd, int x, int y)
{
    char report[5]={0,0,0,0,0};
    report[0] = 0x01;    //左键按下
    report[1] = x & 0xFF;
    report[2] = (x >> 8) & 0xFF;
    report[3] = y & 0xFF;
    report[4] = (y >> 8) & 0xFF;
    if (write(fd, report, 5) != 5) {
        perror("line_to error");
        return;
    }
    usleep(50000);
}

int main(int argc, char const *argv[])
{
    const char *filename = NULL;
    int fd = 0;    

    if (argc != 3) 
    {
            fprintf(stderr, "Usage: %s devname a/l\n",
                    argv[0]);
            return 1;
    }

    filename = argv[1];

    if ((fd = open(filename, O_RDWR, 0666)) == -1) {
        perror(filename);
        return 1;
    }

    if(argv[2][0] == 'a')
    {
        printf("Draw Tri-angle begin\n");
        move_To(fd, 8888, 8888); //移动到(8888,8888)
        line_to(fd, 8888, 8888); //开始画线
        line_to(fd, 12000, 12000); //画线到(12000,12000)        
        move_To(fd, 12000, 12000); //松开鼠标左键

        move_To(fd, 12000, 12000); //移动到(12000,12000)
        line_to(fd, 12000, 12000); //开始画线
        line_to(fd ,8888, 12000); //画线到(8888,12000)
        move_To(fd, 8888, 12000); //松开鼠标左键

        move_To(fd, 8888, 12000); //移动到(8888,12000)
        line_to(fd, 8888, 12000); //开始画线
        line_to(fd ,8888, 8888); //画线到(8888,8888)
        move_To(fd, 8888, 8888); //松开鼠标左键
        printf("Draw Tri-angle end\n");
    }

    if(argv[2][0] == 'l'){
        printf("Draw line begin\n");
        move_To(fd, 10000, 10000);  // 移动到(10000,10000)
        line_to(fd, 10000, 10000);  // 开始画线
        line_to(fd, 20000, 10000);  // 画线到(20000,10000)
        move_To(fd, 20000, 10000);  // 松开鼠标左键
        printf("Draw line end\n");
    }
    
    close(fd);
    return 0;
}

直接在开发板编译应用程序:

root@NanoPC-T6:/opt/hid# gcc -o hid_touch_control hid_touch_control.c
root@NanoPC-T6:/opt/hid# ls -l
-rwxr-xr-x 1 root root 13872 12月 23 13:55 hid_touch_control
-rw-r--r-- 1 root root  2911 12月 23 13:55 hid_touch_control.c
-rwxr-xr-x 1 root root  2668 12月 23 13:47 hid_touch.sh
-rwxrwxr-x 1 pi pi 13170  5月 19  2023 usbdevice
4.5.3 测试触摸屏

(1) 这里我们和鼠标测试一样,使用Type-C连接线将开发板USB3.0 Type-C接口与开发板上的USB3.0 Type-A接口连接起来;内核日志信息如下:

[ 1255.881053] dwc3 fc000000.usb: device reset
[ 1256.004255] usb 1-1: new high-speed USB device number 12 using xhci-hcd
[ 1256.004407] android_work: sent uevent USB_STATE=CONNECTED
[ 1256.007939] dwc3 fc000000.usb: device reset
[ 1256.145009] usb 1-1: New USB device found, idVendor=0525, idProduct=a4ac, bcdDevice= 6.01
[ 1256.145026] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 1256.145035] usb 1-1: Product: touch_screen
[ 1256.145042] usb 1-1: Manufacturer: mkelehk
[ 1256.145048] usb 1-1: SerialNumber: 76543210
[ 1256.150185] android_work: sent uevent USB_STATE=CONFIGURED
[ 1256.151169] input: mkelehk touch_screen as /devices/platform/usbdrd3_1/fc400000.usb/xhci-hcd.9.auto/usb1/1-1/1-1:1.0/0003:0525:A4AC.0017/input/input28
[ 1256.207775] hid-generic 0003:0525:A4AC.0017: input,hidraw0: USB HID v1.01 Mouse [mkelehk touch_screen] on usb-xhci-hcd.9.auto-1/input0

USB触摸屏工作在高速模式下,xHCI控制器,USB2.0通信协议,使用的USB总线编号为1,设备编号为1。

其中Product=touch_screenManufacturer=mkelehkSerialNumber=76543210idVendor=0525idProduct=a4ac,这个就是我们在hid_touch.sh脚本下配置的。

(2) 在开发板ubuntu桌面安装画图软件,并运行程序;

root@rk3588:/shell/hid# sudo aptitude install -y kolourpaint
root@rk3588:/shell/hid# kolourpaint

我们将画布调到最大,并且选择左侧的直线;

Rockchip RK3588 - USB基础 & 调试_第13张图片

(3) 打开一个开发板终端(非桌面终端)输入如下命令:

root@rk3588:/shell/hid# ./hid_touch_control /dev/hidg0 a
Draw Tri-angle begin
Draw Tri-angle end
root@rk3588:/shell/hid# ./hid_touch_control /dev/hidg0 l
Draw line begin
Draw line end

最终得到如下图:

Rockchip RK3588 - USB基础 & 调试_第14张图片

参考文章

[1] Rockchip_Developer_Guide_USB_CN.pdf

[2] Rockchip RK3588 USB开发指南

[3] [Rockchip_Developer_Guide_Linux_USB_PHY_CN]

[4] Rockchip RK3399 - USB调试

[5] Rockchip RK3399 - 移植uboot 2017.09 & linux 4.19(友善之家脚本方式)

你可能感兴趣的:(Rockchip RK3588 - USB基础 & 调试)