rt-thread/bsp/phytium/libraries/standalone/doc/reference/driver/fpcie.md

451 lines
9.5 KiB
Markdown
Raw Normal View History

# FPCIE 驱动程序
## 1. 概述
- PCIe总线使用端到端的连接方式在一条PCIe链路的两端只能各连接一个设备这两个设备互为是数据发送端和数据接收端。PCIe总线除了总线链路外还具有多个层次发送端发送数据时将通过这些层次而接收端接收数据时也使用这些层次。似
- FPCIE 模块内置两个 PCIE 单元PCI-E UnitPEU分别为 PEU0 和 PEU1。每个 PEU 包含 3 个控制器C0、C1 和 C2。当 PEU 拆分模式为 X16 时C1 不可见。
- 本模块特点如下
1. 支持 Root Complex 和 End Point 两种模式;
2. 共 34 lane两路 X16可拆分为 2 个 X8和两路 X1
3. 内部集成 DMA 引擎,一读一写两个通道。
## 2. 功能
- 驱动相关的源文件如下,
- drivers/pcie/fpcie
```
.
├── fpcie.c
├── fpcie.h
├── fpcie.md
├── fpcie_common.h
├── fpcie_config.c
├── fpcie_dma.c
├── fpcie_dma.h
├── fpcie_ep.c
├── fpcie_g.c
├── fpcie_hw.c
├── fpcie_hw.h
├── fpcie_misc.c
├── fpcie_sinit.c
├── fpcir_intx.c
└── fspim.md
```
## 3. 配置方法
以下部分将指导您完成 PCIE 驱动的软件配置:
- 初始化PCIE控制器
- 通过API 获取特定设备的 bar 空间地址
- 使用INTX 中断响应设备中断响应函数
- 使用DMA模式完成数据通信
## 4. 应用示例
"/baremetal/example/peripheral/fpcie_probe "
## 5. API参考
### 5.1 用户数据结构
- 中断注册回调函数
```c
typedef struct
{
void (*IntxCallBack)(void *args) ;
void *args ;
s32 bdf ;
} FPcieIntxFun;
```
- 初始化配置空间地址
```c
struct FPcieRegion {
FPcieAddr bus_start; /* Start on the bus */
FPciePhysAddr phys_start; /* Start in physical address space */
FPcieSize size; /* Size */
unsigned long flags; /* Resource flags */
FPcieAddr bus_lower;
u32 exist_flg; /* exist flg */
};
```
- 驱动配置数据
```c
typedef struct
{
u32 instance_id; /* Id of device */
u32 irq_num; /* Irq number */
uintptr_t ecam; /* The Memory way */
uintptr_t peu0_config_address;
uintptr_t peu1_config_address;
uintptr_t control_c0_address;
uintptr_t control_c1_address;
uintptr_t control_c2_address;
uintptr_t control_c3_address;
uintptr_t control_c4_address;
uintptr_t control_c5_address;
u32 io_base_addr;
u32 io_size ;
u32 npmem_base_addr;
u32 npmem_size;
u64 pmem_base_addr; /* Prefetchable memory */
u64 pmem_size;
u8 inta_irq_num ;
u8 intb_irq_num ;
u8 intc_irq_num ;
u8 intd_irq_num ;
u8 need_skip ;
} FPcieConfig;
```
- 驱动控制数据
```c
typedef struct
{
u32 is_ready; /* Device is ininitialized and ready*/
FPcieConfig config;
struct FPcieRegion mem;
struct FPcieRegion mem_prefetch;
struct FPcieRegion mem_io;
s32 bus_max; /* 当前最大bus num */
FPcieIrqCallBack fpcie_dma_rx_cb;
void *dma_rx_args;
FPcieIrqCallBack fpcie_dma_tx_cb;
void *dma_tx_args;
FPcieIrqCallBack fpcie_dma_rx_error_cb;
void *dma_rx_error_args;
FPcieIrqCallBack fpcie_dma_tx_error_cb;
void *dma_tx_error_args;
FPcieIntxFun inta_fun;
FPcieIntxFun intb_fun;
FPcieIntxFun intc_fun;
FPcieIntxFun intd_fun;
} FPcie;
```
- 配置空间标记参数
```
#define FPCIE_REGION_MEM 0x00000000 /* PCI memory space */
#define FPCIE_REGION_IO 0x00000001 /* PCI IO space */
#define PCI_REGION_PREFETCH 0x00000008 /* prefetchable PCI memory */
```
- 配置空间中对应的bar 标号
```
#define FPCIE_BAR_0 0
#define FPCIE_BAR_1 1
#define FPCIE_BAR_2 2
#define FPCIE_BAR_3 3
#define FPCIE_BAR_4 4
#define FPCIE_BAR_5 5
```
### 5.2 错误码定义
- 模块错误码编号0x1090000
- [0x0] FT_SUCCESS
- [0x1090001] FPCIE_ERR_INVALID_PARAM
- [0x1090002] FPCIE_ERR_OUTOF_BUS
- [0x1090003] FPCIE_ERR_CONFIG_WRITE
- [0x1090004] FPCIE_ERR_TYPE0
- [0x1090005] FPCIE_ERR_TIMEOUT
- [0x1090006] FPCIE_NEED_SKIP
- [0x1090007] FPCIE_NOT_FOUND
### 5.3 用户API接口
#### FPcieLookupConfig
- 获取FPCIE驱动的默认配置参数
```c
const FPcieConfig *FPcieLookupConfig(u32 instance_id)
```
Note:
- 用户可以通过此接口获取驱动默认配置的副本,进行修改后,作为`FPcieCfgInitialize`函数的入参使用
Input:
- u32 instance_id, 选择的FPcie控制器实例号
Return:
- const FPcieConfig *, 返回的默认驱动配置返回NULL表示失败
#### FPcieCfgInitialize
- 初始化配置空间和FPCIE 实例
```c
FError FPcieCfgInitialize(FPcie *instance_p, FPcieConfig *config_p)
```
Note:
- 用户可以使用'FPcieLookupConfig'所产生的配置参数进行初始化,也可以自己组织配置参数进行初始化
Input:
- FPcie *instance_p 指向FPcie实例的指针。
- FPcieConfig *config_p 指向FPcieConfig的指针。
Return :
- 成功返回 FT_SUCCESS
#### FPcieDmaDescSet
- PCIE DMA描述符分组包
```c
FError FPcieDmaDescSet(uintptr axi_addr,
uintptr bar_addr,
u32 length,
struct FPcieDmaDescriptor *desc,
struct FPcieDmaDescriptor *next_desc)
```
Note:
- 用户使用dma 方式进行PCIE 数据传输时,用此函数将源地址与目标地址进行组合打包
Input:
- uintptr axi_addr 内存地址,可以为接收地址也可为发送地址
- uintptr bar_addr 需要通信function中对应的bar寄存器中分配的地址空间可以为接收地址也可为发送地址
- u32 length 需要传输的字节长度
- struct FPcieDmaDescriptor *next_desc 是下一个需要发送的描述符
Output:
- struct FPcieDmaDescriptor *desc 需要要配置的描述符
#### FPcieDmaRead
Note:
- 通过dma的方式读取Pcie function
```c
void FPcieDmaRead(uintptr bar_address, struct FPcieDmaDescriptor *desc)
```
Input:
- uintptr bar_address 基地地址寄存器的值
- struct FPcieDmaDescriptor *desc 接收描述符的起始地址
#### FPcieDmaWrite
- 通过dma的方式写入Pcie function
```c
void FPcieDmaWrite(uintptr bar_address, struct FPcieDmaDescriptor *desc)
```
Input:
- uintptr bar_address 基地地址寄存器的值
- struct FPcieDmaDescriptor *desc 发送描述符的起始地址
#### FPcieDmaPollDone
- 轮询等待DMA完成
```c
FError FPcieDmaPollDone(struct FPcieDmaDescriptor *desc, u32 wait_cnt)
```
Input:
- struct FPcieDmaDescriptor *desc Desc是需要等待完成的dma 描述符
- u32 wait_cnt 是需要等待结束的计数
#### FPcieFetchDeviceInBus
- 该功能用于扫描整个总线上的树形结构,并且对其中的节点进行初始化与配置空间的设置
```c
FError FPcieFetchDeviceInBus(FPcie *instance_p, u32 bus_num)
```
Input:
- FPcie *instance_p 指向FPcie实例的指针。
- u32 bus_num 扫描对应总线上已经连接的网桥/端点。
Output:
- FError FT_SUCCESS 为成功
#### FPcieFindDeviceNum
- 根据输入的Vendor ID 与 Device ID 获取当前PCIE 总线上一共存在多少此类设备
```c
u32 FPcieFindDeviceNum(FPcie *instance_p, u32 bus_num,u32 vendor_id,u32 device_id)
```
Input:
- FPcie *instance_p 指向FPcie实例的指针。
- u32 bus_num 需要查找的bus号
- u32 vendor_id 目标 Vendor ID
- u32 device_id 目标 Device ID
Output:
- u32 return 所需查找设备的数量
#### FPcieGetBusDeviceBarInfo
- 通过Vendor ID和device ID获取对应的function id、device id 和 bar 空间
```c
FError FPcieGetBusDeviceBarInfo(FPcie *instance_p,u32 bus,u32 vendor_id,u32 device_id,u32 bar_num ,u32 *device_p,u32 *function_p,uintptr *bar_addr_p)
```
Input:
- FPcie *instance_p 指向FPcie实例的指针。
- u32 bus 需要查找的bus号
- u32 vendor_id 目标 Vendor ID
- u32 device_id 目标 Device ID
- u32 bar_num 需要查找对应bar空间的编号
Output:
- u32 * device_p 需要获取对应设备号的指针
- u32 * function_p 需要获取对应功能号的指针
- uintptr * bar_addr_p 需要获取对应bar地址空间的指针
- FError return FT_SUCCESS 为成功
#### FPcieSearchFunByClass
- 使用 class code 获取设备的信息
```c
u32 FPcieSearchFunByClass(FPcie *instance_p,u32 class_code,FPcieSearchFunNode *node_p ,u32 node_num)
```
Input:
- FPcie *instance_p 指向FPcie实例的指针。
- u32 class_code 对应的类号
- FPcieSearchFunNode * node_p 是一个存放特定函数信息缓冲区的指针
- u32 node_num 缓冲器的数量
Output:
- u32 return 输出中的实际节点的个数
#### FPcieIntxIrqHandler
- fpcie的Intx中断服务函数
```c
void FPcieIntxIrqHandler(s32 vector, void *args)
```
Input:
- s32 vector 中断向量号
- void * args 需要传入的参数
#### FPcieIntxRegiterIrqHandler
- 使用bus id、device id 和function id在INTX上注册中断响应函数
```c
FError FPcieIntxRegiterIrqHandler(FPcie *instance_p,
u32 bus,
u32 device,
u32 function,
FPcieIntxFun *intx_fun_p)
```
Input:
- FPcie *instance_p 指向FPcie实例的指针。
- u32 bus 需要配置的bus id
- u32 device 需要配置的device id
- u32 function 需要配置的function id
- FPcieIntxFun * intx_fun_p 是用户用来注册回调函数信息的指针