summaryrefslogtreecommitdiff
path: root/bsp/phytium/libraries/standalone/doc/reference/driver/fpcie.md
blob: 4a93dd9539d9b674972e1c1338cbbf4abfb82df3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
# FPCIE 驱动程序

## 1. 概述


- PCIe总线使用端到端的连接方式,在一条PCIe链路的两端只能各连接一个设备,这两个设备互为是数据发送端和数据接收端。PCIe总线除了总线链路外,还具有多个层次,发送端发送数据时将通过这些层次,而接收端接收数据时也使用这些层次。似

- FPCIE 模块内置两个 PCIE 单元(PCI-E Unit,PEU),分别为 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 是用户用来注册回调函数信息的指针