本文以QCOM平台为例分析
PCIe RC driver
PCIe RC probe
1. RC driver和device tree通过名字匹配成功后调用msm_pcie_probe函数
2. msm_pcie_probe工作主要包含:
• 解析dts,获取时钟,电压,中断,memory资源以及配置信息
• 根据boot_option选项决定是否枚举设备,即调用msm_pcie_enumerate()函数(Qcom提供了三种可供选择的设备枚举时机)
RC触发设备枚举(msm_pcie_enumerate)
1. 使能电压,时钟,配置PCIe到RC mode,pcie-phy初始化,link-trainning等.
2. 分配struct pci_host_bridge 内存,并初始化
3. 获取PCI总线范围”bus-range”和地址空间范围”ranges”
4. 向内核申请host_bridge_resource资源
5. MSI初始化
6. 初始化pci_ops,用来读写配置空间
7. map irq
8. 递归遍历pci bus及其pci 子bus上的所有设备
9. 分配bus resource,即初始化BAR空间
10. 递归probe pci_bus及其子总线上的所有devices
递归遍历设备(深度优先算法)
pci_scan_root_bus_bridge 参考:PCIe 基础知识 中的PCIe设备枚举的软件实现
PCIe设备probe流程
1. 首先遍历当前pci bus上的所有devices,如果vendor ID和device ID匹配成功则调用当前bus_type中的probe成员,bus_type在pci_setup_device函数中初始化,即最终调用到pci_device_probe
2. 再遍历当前pci bus子总线上的所有devices,直到所有子总线上的devices被probe
3. pci_device_probe函数最终调用function的probe函数,进行function的初始化;即function调用pci_register_driver(struct pci_driver)函数注册pci驱动时,传入的结构体struct pci_driver参数的probe成员函数
PCIe endpoint driver
以USB endpoint为例:
路径:drivers/usb/dwc3/dwc3-pci.c
1. 初始化pci_device_id结构体
2. 初始化pci_driver结构体
3. 注册driver到PCIe Framework
PCIe与USB的交互
1. 向PCI Framework注册pci driver
2. 在PCIe枚举(pci_scan_root_bus_bridge)过程中,通过BDF读设备的vendor ID和device ID,有效则添加到PCIe设备树(bus链表,设备链表)中,然后pci_bus_add_devices依次遍历PCIe设备树上的device,并触发device和driver的匹配,匹配方式就是判断设备vendor ID&device ID和struct pci_device_id中初始化的vendor ID&device ID是否相等,相等则触发struct pci_driver中初始化的probe函数,对于该示例来说就是dwc3_pci_porbe()函数
3. 通过RC提供的配置空间读写接口操作配置空间的寄存器
4. 获取BAR寄存器的值和irq信息
5. 保存BAR的内容和中断信息到平台设备
6. 添加平台设备到系统,该过程会触发device和driver的匹配(根据名字匹配),匹配成功则调用该driver的probe函数(dwc3_probe)
7. dwc3_probe创建并添加平台设备“xhci-hcd”,并触发device和driver的匹配(根据名字匹配),匹配成功则调用该driver的probe函数(xhci_plat_probe),进入usb初始化流程
8. 获取步骤5中BAR的内容
9. 映射BAR指向的地址到虚拟地址空间,CPU对EP memory的访问即对该虚拟地址的读写
10. 获取步骤5中保存的中断信息
11. 注册中断
PCIe 与 USB 核心数据结构
struct pci_dev
成员dev的driver_data成员指向dwc3_pci数据
struct dwc3_pci
成员dev的driver_data成员指向dwc3数据
struct dwc3
成员xhci即为platform_device数据
struct xhci_hcd
成员main_hcd指向usb2.0控制器
成员shared_hcd指向usb3.x控制器
struct usb_hcd
usb控制器核心结构体
成员self的controller成员指向platform_device的device成员
struct hc_driver
操作函数集