首页 理论教育PCIExpress初始化指南

PCIExpress初始化指南

【摘要】:Linux PowerPC初始化PCI总线树的步骤与Linux x86类似,也调用了一些Linux系统中与PCI总线相关的通用函数。但是PowerPC处理器使用的HOST主桥与x86处理器并不相同,因此Linux PowerPC初始化PCI总线树的过程与Linux x86有些差别。本节以MPC8572处理器为例,说明Linux PowerPC初始化PCI总线树的过程。Linux PowerPC在引入了Open Firmware机制[22]后,使用dts文件管理PCI总线控制器。Linux PowerPC执行完毕setup_arch函数后,还会执行一些和PCI总线

Linux PowerPC初始化PCI总线树的步骤与Linux x86类似,也调用了一些Linux系统中与PCI总线相关的通用函数。但是PowerPC处理器使用的HOST主桥与x86处理器并不相同,因此Linux PowerPC初始化PCI总线树的过程与Linux x86有些差别。本节以MPC8572处理器为例,说明Linux PowerPC初始化PCI总线树的过程。

MPC8572处理器共有三个PCIe总线控制器,其中每一个总线控制器都可以管理一个独立的PCI总线树。在每一个总线控制器中都包含一组独立的寄存器,MPC8572处理器可以通过设置Inbound和Outbound寄存器,访问对应PCI总线树上所有PCI设备的配置空间。这组寄存器与MPC8548处理器提供的对应寄存器较为类似,详见第2.2节。

Linux PowerPC在引入了Open Firmware机制[22]后,使用dts文件管理PCI总线控制器。MPC8572处理器系统使用的dts文件为./arch/powerpc/boot/dts/mpc8572ds.dts文件,其中与PCI总线控制器相关的部分如源代码14-43所示。

源代码14-43 MPC8572处理器系统使用的dts文件

以上代码分别描述了MPC8572处理器系统的3个PCIe控制器,其使用的寄存器空间为0xFFE08000~0xFFE08FFFF、0xFFE09000~0xFFE09FFFF和0xFFE0A000~0xFFE0AFFFF。这三个PCIe控制器分别管理3棵PCI总线树,其PCI总线的编号都为0~255,在这个dts文件中还包含了PCIe控制器的其他信息,本节并不关心这些内容。

Linux PowerPC在调用setup_arch→mpc85xx_cds_setup_arch函数时,分别初始化这三个PCIe控制器,该函数的实现如源代码14-44所示。

源代码14-44 mpc85xx_cds_setup_arch函数

mpc85xx_cds_setup_arch函数分析mpc8572ds.dts文件,并将“pci0”作为主PCI总线控制器,并调用fsl_add_bridge(np,1)函数进行初始化操作,“pci1”和“pci2”作为从PCI总线控制器调用fsl_add_bridge(np,0)函数进行初始化操作。在MPC8572处理器中,主PCI总线控制器需要处理ISA总线使用的存储器和I/O地址空间。

fsl_add_bridge函数在./arch/powerpc/sysdev/fsl_pci.c文件中,该函数的实现如源代码14-45~26所示。Linux PowerPC使用pci_controller结构描述HOST主桥,包括这个主桥管理的PCI总线域地址范围、PCI总线号和访问配置寄存器的方法等一系列信息,pci_controller结构在./arch/powerpc/include/asm/pci-bridge.h文件中。

源代码14-45 fsl_add_bridge函数片段1

这段代码首先分析mpc8572ds.dts文件,然后获得PCIe主桥管理的PCI总线范围,对于pci0控制器,bus_range[0]为0,而bus_range[1]为255。之后为当前PCIe主桥使用的hose结构分配空间,并初始化其first_busno和last_busno参数。

setup_indirect_pci函数设置在Linux PowerPC中间接访问PCI设备配置空间的函数,如第2.2节所示,在PowerPC处理器中,访问PCI设备配置空间有两种方式,一种是使用间接访问方式,一种是使用ECAM方式。与x86处理器略有不同,PowerPC处理器使用间接访问方式也可以访问PCIe设备的扩展配置空间,因此ECAM方式对于PowerPC处理器而言,并不是必须的。

源代码14-46 fsl_add_bridge函数片段2

pci_process_bridge_OF_ranges函数分析mpc8572ds.dts文件的“ranges”字段,在dts文件中,ranges字段的解释如下。

ranges字段共由14个双字组成,每7个双字为1组,每一组描述一段PCI总线域地址空间与存储器域地址空间的对应关系。

●每一组的第一个双字代表pci_space,为0x200-0000表示这段PCI总线地址空间为存储器地址空间,为0x100-0000表示这段PCI总线地址空间为I/O地址空间。

●每一组的第2~3个双字存放pci_address,即PCI域地址空间。(www.chuimin.cn)

●每一组的第4~5个双字存放cpu_address,即存储器域地址空间。

●每一组的第6~7个双字存放size,即这段地址空间的大小。

pci_process_bridge_OF_ranges函数的主要作用就是根据dts文件中的ranges字段,初始化hose结构的对应参数,本节对该函数不做进一步介绍。

setup_pci_atmu函数首先设置MPC8572处理器中的Outbound和Inbound寄存器组,这两组寄存器的描述见第2.2节。然后设置PEXCSRBAR寄存器。

如果MPC8572处理器作为RC[23],而且支持MSI中断机制时,需要设置PCIe主桥的BAR0寄存器,即PEXCSRBAR(PCI Express Base Address Register)寄存器。在PCI规范中,MSI中断机制以存储器写的方式实现,当这个MSI存储器写最终到达RC时,需要能够被RC接收。在PowerPC处理器中,MSI存储器写的目的地址为MSIIR寄存器在PCI总线域的物理地址。此时PowerPC处理器可以采用两种方式接收这个MSI存储器写,一种是设置Inbound寄存器,映射MSIIR寄存器所在的PCI总线空间,另一种是设置RC的BAR0寄存器。Linux PowerPC使用了后一种方式。

Linux PowerPC执行完毕setup_arch函数后,还会执行一些和PCI总线初始化相关的函数,如下所示。

c053e04c t__initcall_pcibus_class_init2

c053e050 t__initcall_pci_driver_init2

c053e088 t__initcall_pcibios_init4

c053e0ac t__initcall_pci_slot_init4

c053e28c t__initcall_pci_init6

c053e290 t__initcall_pci_proc_init6

c053e3ec t__initcall_pci_resource_alignment_sysfs_init7

c053e3f0 t__initcall_pci_sysfs_init7

这些函数在第14.3节中都有介绍,虽然Linux PowerPC执行这些函数的过程与Linux x86略有不同,但大体类似,本章对此不做进一步说明。