]> git.proxmox.com Git - mirror_edk2.git/blame - QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/PciExpress.c
QuarkSocPkg: Add new package for Quark SoC X1000
[mirror_edk2.git] / QuarkSocPkg / QuarkNorthCluster / Library / IntelQNCLib / PciExpress.c
CommitLineData
9b6bbcdb
MK
1/** @file\r
2QNC PCI Express initialization entry\r
3\r
4Copyright (c) 2013-2015 Intel Corporation.\r
5\r
6This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "CommonHeader.h"\r
17\r
18#define PCIEXP_ROOT_PORT_URE_ENABLE BIT0 // unsupported request reporting enable\r
19#define PCIEXP_ROOT_PORT_FEE_ENABLE BIT1 // Fatal Error Reporting Enable\r
20#define PCIEXP_ROOT_PORT_NFE_ENABLE BIT2 // Non-Fatal Error Reporting Enable\r
21#define PCIEXP_ROOT_PORT_CEE_ENABLE BIT3 // Correctable Error Reporting Enable\r
22#define PCIEXP_ROOT_PORT_SFE_ENABLE BIT4 // System Error on Fatal Error Enable\r
23#define PCIEXP_ROOT_PORT_SNE_ENABLE BIT5 // System Error on Non-Fatal Error Enable\r
24#define PCIEXP_ROOT_PORT_SCE_ENABLE BIT6 // System Error on Correctable Error Enable\r
25\r
26EFI_STATUS\r
27PcieStall (\r
28 IN UINTN Microseconds\r
29 )\r
30{\r
31 MicroSecondDelay (Microseconds);\r
32 return EFI_SUCCESS;\r
33}\r
34\r
35/**\r
36\r
37 Find the Offset to a given Capabilities ID\r
38 CAPID list:\r
39 0x01 = PCI Power Management Interface\r
40 0x04 = Slot Identification\r
41 0x05 = MSI Capability\r
42 0x10 = PCI Express Capability\r
43\r
44 @param[in] Bus Bus number of the interested device\r
45 @param[in] Device Device number of the interested device\r
46 @param[in] Function Function number of the interested device\r
47 @param[in] CapId Capability ID to be scanned\r
48\r
49 @retval Offset of desired CAPID\r
50\r
51**/\r
52UINT32\r
53PcieFindCapId (\r
54 UINT8 Bus,\r
55 UINT8 Device,\r
56 UINT8 Function,\r
57 UINT8 CapId\r
58 )\r
59{\r
60 UINT8 CapHeader;\r
61\r
62 //\r
63 // Always start at Offset 0x34\r
64 //\r
65 CapHeader = QNCMmPci8 (0, Bus, Device, Function, R_QNC_PCIE_CAP_PTR);\r
66\r
67 if (CapHeader == 0xFF) {\r
68 return 0;\r
69 }\r
70\r
71 while (CapHeader != 0) {\r
72 if (QNCMmPci8 (0, Bus, Device, Function, CapHeader) == CapId) {\r
73 return CapHeader;\r
74 }\r
75 CapHeader = QNCMmPci8 (0, Bus, Device, Function, CapHeader + 1);\r
76 }\r
77 return 0;\r
78}\r
79\r
80/**\r
81\r
82 Search and return the offset of desired Pci Express Capability ID\r
83 CAPID list:\r
84 0x0001 = Advanced Error Rreporting Capability\r
85 0x0002 = Virtual Channel Capability\r
86 0x0003 = Device Serial Number Capability\r
87 0x0004 = Power Budgeting Capability\r
88\r
89 @param[in] Bus Bus number of the interested device\r
90 @param[in] Device Device number of the interested device\r
91 @param[in] Function Function number of the interested device\r
92 @param[in] CapId Capability ID to be scanned\r
93\r
94 @retval Offset of desired CAPID\r
95\r
96**/\r
97UINT32\r
98PcieFindExtendedCapId (\r
99 UINT8 Bus,\r
100 UINT8 Device,\r
101 UINT8 Function,\r
102 UINT16 CapId\r
103 )\r
104{\r
105 UINT16 CapHeaderOffset;\r
106 UINT16 CapHeaderId;\r
107\r
108 // Start to search at Offset 0x100\r
109 // Get Capability Header\r
110 CapHeaderId = 0;\r
111 CapHeaderOffset = PCIE_CAP_EXT_HEARDER_OFFSET;\r
112\r
113 while (CapHeaderOffset != 0 && CapHeaderId != 0xFFFF) {\r
114 CapHeaderId = QNCMmPci16 (0, Bus, Device, Function, CapHeaderOffset);\r
115 if (CapHeaderId == CapId) {\r
116 return CapHeaderOffset;\r
117 }\r
118 CapHeaderOffset = (QNCMmPci16 (0, Bus, Device, Function, CapHeaderOffset + 2) >> 4);\r
119 }\r
120 return 0;\r
121}\r
122\r
123/**\r
124\r
125 Map Vc on both root port and downstream device\r
126\r
127 @param[in] Bus1 Bus number of the root port\r
128 @param[in] Device1 Device number of the root port\r
129 @param[in] Function1 Function number of the root port\r
130 @param[in] Bus2 Bus number of the downstream device\r
131 @param[in] Device2 Device number of the downstream device\r
132 @param[in] Function2 Function number of the downstream device\r
133\r
134 @retval EFI_SUCCESS Map Vc successful\r
135\r
136**/\r
137EFI_STATUS\r
138PcieInitTcxVc0 (\r
139 IN UINT8 Bus1,\r
140 IN UINT8 Device1,\r
141 IN UINT8 Function1,\r
142 IN UINT8 Bus2,\r
143 IN UINT8 Device2,\r
144 IN UINT8 Function2\r
145 )\r
146{\r
147 UINT32 Offset;\r
148\r
149 //\r
150 // Initialize TCx-VC0 value on the port to only use TC0\r
151 //\r
152 Offset = PcieFindExtendedCapId (Bus1, Device1, Function1, 2);\r
153 if (Offset == 0) {\r
154 return EFI_UNSUPPORTED;\r
155 }\r
156 QNCMmPci8AndThenOr (0, Bus1, Device1, Function1, (Offset + PCIE_SLOT_CAP_OFFSET), ~0xF, 1);\r
157\r
158 // Set TCx-VC0 value on the Endpoint\r
159\r
160 Offset = PcieFindExtendedCapId (Bus2, Device2, Function2, 2);\r
161 if (Offset == 0) {\r
162 return EFI_UNSUPPORTED;\r
163 }\r
164 QNCMmPci8AndThenOr (0, Bus2, Device2, Function2, (Offset + PCIE_SLOT_CAP_OFFSET), ~0xF, 1);\r
165\r
166 return EFI_SUCCESS;\r
167}\r
168\r
169/**\r
170\r
171 Map Traffic Class x to Vc0 on both root port and downstream device\r
172\r
173 @param[in] Bus1 Bus number of the root port\r
174 @param[in] Device1 Device number of the root port\r
175 @param[in] Function1 Function number of the root port\r
176 @param[in] Bus2 Bus number of the downstream device\r
177 @param[in] Device2 Device number of the downstream device\r
178 @param[in] Function2 Function number of the downstream device\r
179 @param[in] TCx Traffic Class to be mapped to vc0\r
180\r
181 @retval EFI_SUCCESS Map Tcx to Vc0 successful\r
182\r
183**/\r
184EFI_STATUS\r
185PcieMapTcxVc0 (\r
186 IN UINT8 Bus1,\r
187 IN UINT8 Device1,\r
188 IN UINT8 Function1,\r
189 IN UINT8 Bus2,\r
190 IN UINT8 Device2,\r
191 IN UINT8 Function2,\r
192 IN UINT8 TCx\r
193 )\r
194{\r
195 UINT32 Offset;\r
196\r
197 //\r
198 // Set TCx-VC0 value on the port\r
199 //\r
200\r
201 Offset = PcieFindExtendedCapId (Bus1, Device1, Function1, 2);\r
202 if (Offset == 0) {\r
203 return EFI_UNSUPPORTED;\r
204 }\r
205 QNCMmPci8 (0, Bus1, Device1, Function1, (Offset + PCIE_SLOT_CAP_OFFSET)) = (UINT8)(1 << TCx);\r
206\r
207 // Set TCx-VC0 value on the Endpoint\r
208\r
209 Offset = PcieFindExtendedCapId (Bus2, Device2, Function2, 2);\r
210 if (Offset == 0) {\r
211 return EFI_UNSUPPORTED;\r
212 }\r
213 QNCMmPci8 (0, Bus2, Device2, Function2, (Offset + PCIE_SLOT_CAP_OFFSET)) = (UINT8)(1 << TCx);\r
214\r
215 return EFI_SUCCESS;\r
216}\r
217\r
218/**\r
219\r
220 Set common clock for both root port and downstream device.\r
221\r
222 @param[in] Bus1 Bus number of the root port\r
223 @param[in] Device1 Device number of the root port\r
224 @param[in] Function1 Function number of the root port\r
225 @param[in] Bus2 Device number of the downstream device\r
226 @param[in] Device2 Function number of the downstream device\r
227\r
228 @retval EFI_SUCCESS Set common clock successful\r
229\r
230**/\r
231EFI_STATUS\r
232PcieSetCommonClock (\r
233 IN UINT8 Bus1,\r
234 IN UINT8 Device1,\r
235 IN UINT8 Function1,\r
236 IN UINT8 Bus2,\r
237 IN UINT8 Device2\r
238 )\r
239{\r
240 UINT32 CapOffset1;\r
241 UINT32 CapOffset2;\r
242 UINT8 Function2;\r
243 UINT8 CommonClock;\r
244 EFI_STATUS Status;\r
245\r
246 //\r
247 // Get the pointer to the Port PCI Express Capability Structure.\r
248 //\r
249 CommonClock = 0;\r
250 CapOffset1 = PcieFindCapId (Bus1, Device1, Function1, PCIE_CAPID);\r
251 if (CapOffset1 == 0) {\r
252 return EFI_UNSUPPORTED;\r
253 }\r
254\r
255 //\r
256 // Step 1\r
257 // Read the Slot Clock Configuration bit of the Link status register of the root port and the endpoint device connected to the port\r
258 // If both components have this bit set to 1, then System BIOS should set the "Common Clock Configuration" bit in the Link Control Registers\r
259 // for both components at both sides of the link to indicate that components at both ends\r
260 // of the link use a common clock source\r
261 //\r
262\r
263 //\r
264 // Check the Port Slot Clock Configuration Bit.\r
265 //\r
266 if ((QNCMmPci16 (0, Bus1, Device1, Function1, (CapOffset1 + PCIE_LINK_STS_OFFSET)) & B_QNC_PCIE_LSTS_SCC) == 0) {\r
267 return EFI_UNSUPPORTED;\r
268 }\r
269\r
270 for (Function2 = 0; Function2 < 8; Function2++) {\r
271 //\r
272 // Check the Endpoint Slot Clock Configuration Bit.\r
273 //\r
274 CapOffset2 = PcieFindCapId (Bus2, Device2, Function2, PCIE_CAPID);\r
275 if ((CapOffset2 != 0) &&\r
276 ((QNCMmPci16 (0, Bus2, Device2, Function2, (CapOffset2 + PCIE_LINK_STS_OFFSET)) & B_QNC_PCIE_LSTS_SCC) != 0)) {\r
277\r
278 //\r
279 // Common clock is supported, set common clock bit on root port\r
280 // and the endpoint\r
281 //\r
282 if (CommonClock == 0) {\r
283 QNCMmPci8Or (0, Bus1, Device1, Function1, (CapOffset1 + PCIE_LINK_CNT_OFFSET), B_QNC_PCIE_LCTL_CCC);\r
284 CommonClock++;\r
285 }\r
286 QNCMmPci8Or (0, Bus2, Device2, Function2, (CapOffset2 + PCIE_LINK_CNT_OFFSET), B_QNC_PCIE_LCTL_CCC);\r
287 }\r
288 }\r
289\r
290 //\r
291 // Step 2 If the Common Clock Configuration bit was changed by BIOS in step 1,\r
292 // System BIOS should initiate a link training by setting the Retrain Link bit\r
293 // in the Link Control register of the root port (D28:F0/F1 offset\r
294 // 50h [5]) to "1b" and then poll the Link Training bit in the Link Status\r
295 // register of the root port (D28:F0/F1/F2/F3/F4/F5 offset 52h [11]) until it is\r
296 // "0b".\r
297 //\r
298 if (CommonClock == 0) {\r
299 Status = EFI_UNSUPPORTED;\r
300 } else {\r
301 //\r
302 // Retrain the Link per PCI Express Specification.\r
303 //\r
304 QNCMmPci8Or (0, Bus1, Device1, Function1, (CapOffset1 + PCIE_LINK_CNT_OFFSET), B_QNC_PCIE_LCTL_RL);\r
305\r
306 //\r
307 // Wait until Re-Training has completed.\r
308 //\r
309 while ((QNCMmPci16 (0, Bus1, Device1, Function1, (CapOffset1 + PCIE_LINK_STS_OFFSET)) & B_QNC_PCIE_LSTS_LT) != 0);\r
310 Status = EFI_SUCCESS;\r
311 }\r
312\r
313 return Status;\r
314}\r
315\r
316/**\r
317\r
318 Enables the CLKREQ# PM on all the end point functions\r
319\r
320 @param[in] Bus Bus number of the downstream device\r
321 @param[in] Device Device number of the downstream device\r
322\r
323 @retval None\r
324\r
325**/\r
326VOID\r
327PcieSetClkreq (\r
328 IN UINT8 Bus,\r
329 IN UINT8 Device\r
330 )\r
331{\r
332 UINT8 Function;\r
333 UINT32 CapOffset;\r
334\r
335 //\r
336 // Parse thro all the functions of the endpoint and find the PCIe Cap ID (offset 10h) and if\r
337 // exists then enable the CLKREQ# bit (BIT8) on that function\r
338 //\r
339 for (Function = 0; Function < 8; Function++) {\r
340 //\r
341 // Find the PCIe Cap Id (offset 10h)\r
342 //\r
343 CapOffset = PcieFindCapId (Bus, Device, Function, PCIE_CAPID);\r
344 if (CapOffset == 0) {\r
345 continue;\r
346 }\r
347\r
348 //\r
349 // Check if CLKREQ# is supported by the endpoints\r
350 //\r
351 if ((QNCMmPci32 (0, Bus, Device, Function, (CapOffset + PCIE_LINK_CAP_OFFSET))\r
352 & B_QNC_PCIE_LCAP_CPM) != B_QNC_PCIE_LCAP_CPM) {\r
353 //\r
354 // CLKREQ# is not supported so dont do anything\r
355 //\r
356 return;\r
357 }\r
358 }\r
359\r
360 //\r
361 // Now enable the CLKREQ#\r
362 //\r
363 for (Function = 0; Function < 8; Function++) {\r
364 //\r
365 // Find the PCIe Cap Id (offset 10h)\r
366 //\r
367 CapOffset = PcieFindCapId (Bus, Device, Function, PCIE_CAPID);\r
368 if (CapOffset == 0) {\r
369 continue;\r
370 }\r
371\r
372 QNCMmPci16Or (0, Bus, Device, Function, (CapOffset + PCIE_LINK_CNT_OFFSET), BIT8);\r
373 }\r
374}\r
375\r
376/**\r
377\r
378 Configure ASPM automatically for both root port and downstream device.\r
379\r
380 @param[in] RootBus Bus number of the root port\r
381 @param[in] RootDevice Device number of the root port\r
382 @param[in] RootFunction Function number of the root port\r
383 @param[in] EndpointBus Bus number of the downstream device\r
384 @param[in] EndpointDevice Device number of the downstream device\r
385 @param[in] EndpointFunction Function number of the downstream device\r
386 @param[in] LinkAspmVal Currently used ASPM setting\r
387\r
388 @retval EFI_SUCCESS Configure ASPM successful\r
389\r
390**/\r
391EFI_STATUS\r
392PcieSetAspmAuto (\r
393 IN UINT8 RootBus,\r
394 IN UINT8 RootDevice,\r
395 IN UINT8 RootFunction,\r
396 IN UINT8 EndpointBus,\r
397 IN UINT8 EndpointDevice,\r
398 IN UINT8 EndpointFunction,\r
399 OUT UINT16 *LinkAspmVal\r
400 )\r
401{\r
402 UINT32 RootPcieCapOffset;\r
403 UINT32 EndpointPcieCapOffset;\r
404 UINT16 RootPortAspm;\r
405 UINT16 EndPointAspm;\r
406 UINT16 EndPointVendorId;\r
407 UINT16 EndPointDeviceId;\r
408 UINT8 EndPointRevId;\r
409 UINT16 AspmVal;\r
410 UINT32 PortLxLat;\r
411 UINT32 EndPointLxLat;\r
412 UINT32 LxLat;\r
413\r
414 //\r
415 // Get the pointer to the Port PCI Express Capability Structure.\r
416 //\r
417 RootPcieCapOffset = PcieFindCapId (RootBus, RootDevice, RootFunction, PCIE_CAPID);\r
418 if (RootPcieCapOffset == 0) {\r
419 return EFI_UNSUPPORTED;\r
420 }\r
421\r
422 //\r
423 // Get the pointer to the Endpoint PCI Express Capability Structure.\r
424 //\r
425 EndpointPcieCapOffset = PcieFindCapId (EndpointBus, EndpointDevice, EndpointFunction, PCIE_CAPID);\r
426 if (EndpointPcieCapOffset == 0) {\r
427 return EFI_UNSUPPORTED;\r
428 }\r
429\r
430 //\r
431 // Obtain initial ASPM settings from respective port capability registers.\r
432 //\r
433 RootPortAspm = (QNCMmPci16 (0, RootBus, RootDevice, RootFunction, (RootPcieCapOffset + PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_APMS_MASK) >> V_QNC_PCIE_LCAP_APMS_OFFSET;\r
434\r
435 //\r
436 // Configure downstream device if present.\r
437 //\r
438 EndPointAspm = (QNCMmPci16 (0, EndpointBus, EndpointDevice, EndpointFunction, (EndpointPcieCapOffset + PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_APMS_MASK) >> V_QNC_PCIE_LCAP_APMS_OFFSET;\r
439\r
440 //\r
441 // Mask APMC with values from lookup table.\r
442 // RevID of 0xFF applies to all steppings.\r
443 //\r
444\r
445 EndPointVendorId = QNCMmPci16 (0, EndpointBus, EndpointDevice, EndpointFunction, 0);\r
446 EndPointDeviceId = QNCMmPci16 (0, EndpointBus, EndpointDevice, EndpointFunction, 2);\r
447 EndPointRevId = QNCMmPci8 (0, EndpointBus, EndpointDevice, EndpointFunction, 8);\r
448\r
449 // TODO: Mask with latency/acceptable latency comparison results.\r
450\r
451 AspmVal = RootPortAspm;\r
452 if (RootPortAspm > EndPointAspm) {\r
453 AspmVal = EndPointAspm;\r
454 }\r
455\r
456 //\r
457 // Check if L1 should be enabled based on port and endpoint L1 exit latency.\r
458 //\r
459 if(AspmVal & BIT1) {\r
460 PortLxLat = QNCMmPci32 (0, RootBus, RootDevice, RootFunction, (RootPcieCapOffset + PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_EL1_MASK;\r
461 EndPointLxLat = QNCMmPci32 (0, EndpointBus, EndpointDevice, EndpointFunction, (EndpointPcieCapOffset + PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_EL1_MASK;\r
462\r
463 LxLat = PortLxLat;\r
464 if(PortLxLat < EndPointLxLat) {\r
465 LxLat = EndPointLxLat;\r
466 }\r
467\r
468 //\r
469 // check if the value is bigger than endpoint L1 acceptable exit latency, if it is\r
470 // larger than accepted value, then we should disable L1\r
471 //\r
472 LxLat >>= 6;\r
473 if(LxLat > (QNCMmPci32 (0, EndpointBus, EndpointDevice, EndpointFunction, (EndpointPcieCapOffset + PCIE_DEV_CAP_OFFSET)) & B_QNC_PCIE_DCAP_E1AL)) {\r
474 AspmVal &= ~BIT1;\r
475 }\r
476 }\r
477\r
478 //\r
479 // Check if L0s should be enabled based on port and endpoint L0s exit latency.\r
480 //\r
481 if(AspmVal & BIT0) {\r
482 PortLxLat = QNCMmPci32 (0, RootBus, RootDevice, RootFunction, (RootPcieCapOffset+ PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_EL0_MASK;\r
483 EndPointLxLat = QNCMmPci32 (0, EndpointBus, EndpointDevice, EndpointFunction, (EndpointPcieCapOffset + PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_EL0_MASK;\r
484\r
485 LxLat = PortLxLat;\r
486 if(PortLxLat < EndPointLxLat) {\r
487 LxLat = EndPointLxLat;\r
488 }\r
489\r
490 //\r
491 // check if the value is bigger than endpoint L0s acceptable exit latency, if it is\r
492 // larger than accepted value, then we should disable L0s\r
493 //\r
494 LxLat >>= 6;\r
495 if(LxLat > (QNCMmPci32 (0, EndpointBus, EndpointDevice, EndpointFunction, (EndpointPcieCapOffset + PCIE_DEV_CAP_OFFSET)) & B_QNC_PCIE_DCAP_E0AL)) {\r
496 AspmVal &= ~BIT0;\r
497 }\r
498 }\r
499\r
500 RootPortAspm = AspmVal;\r
501\r
502 *LinkAspmVal = AspmVal;\r
503 //\r
504 // Set Endpoint Aspm\r
505 //\r
506 QNCMmPci16AndThenOr (0, EndpointBus, EndpointDevice, EndpointFunction, (EndpointPcieCapOffset + PCIE_LINK_CNT_OFFSET), 0xFFFC, AspmVal);\r
507\r
508\r
509 //\r
510 // Set Root Port Aspm\r
511 //\r
512 QNCMmPci16AndThenOr (0, RootBus, RootDevice, RootFunction, (RootPcieCapOffset + PCIE_LINK_CNT_OFFSET), 0xFFFC, RootPortAspm);\r
513\r
514 return EFI_SUCCESS;\r
515}\r
516\r
517/**\r
518\r
519 Configure ASPM based on the given setting for the interested device.\r
520\r
521 @param[in] Bus Bus number of the interested device\r
522 @param[in] Device Device number of the interested device\r
523 @param[in] Function Function number of the interested device\r
524 @param[in] AspmSetting Aspm setting\r
525 @param[in] LinkAspmVal Currently used ASPM setting\r
526\r
527 @retval EFI_SUCCESS Configure ASPM successful\r
528\r
529**/\r
530EFI_STATUS\r
531PcieSetAspmManual (\r
532 IN UINT8 Bus,\r
533 IN UINT8 Device,\r
534 IN UINT8 Function,\r
535 IN UINT8 AspmSetting,\r
536 OUT UINT16 *LinkAspmVal\r
537 )\r
538{\r
539 UINT32 PcieCapOffset;\r
540 UINT16 PortAspm;\r
541\r
542 //\r
543 // Get the pointer to the Port PCI Express Capability Structure.\r
544 //\r
545 PcieCapOffset = PcieFindCapId (Bus, Device, Function, PCIE_CAPID);\r
546 if (PcieCapOffset == 0) {\r
547 return EFI_UNSUPPORTED;\r
548 }\r
549\r
550 // Read the Link Capability register's ASPM setting\r
551 PortAspm = (QNCMmPci16 (0, Bus, Device, Function, (PcieCapOffset + PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_APMS_MASK) >> V_QNC_PCIE_LCAP_APMS_OFFSET;\r
552 // Mask it with the Setup selection\r
553 PortAspm &= AspmSetting;\r
554\r
555 *LinkAspmVal = PortAspm;\r
556 // Write it to the Link Control register\r
557 QNCMmPci16AndThenOr (0, Bus, Device, Function, (PcieCapOffset + PCIE_LINK_CNT_OFFSET), 0xFFFC, PortAspm);\r
558\r
559 return EFI_SUCCESS;\r
560}\r
561\r
562/**\r
563\r
564 Perform Initialization on one PCI Express root port.\r
565\r
566 @param[in] RootPortIndex Index of PCI Express root port\r
567 @param[in] RootPortConfig Pointer to the given pcie root port configuration\r
568 @param[in] PciExpressBar Base address of pcie space\r
569 @param[in] QNCRootComplexBar Base address of root complex\r
570 @param[in] QNCPmioBase Base address of PM IO space\r
571 @param[in] QNCGpeBase Base address of gpe IO space\r
572\r
573 @retval EFI_SUCCESS Initialization successful\r
574\r
575**/\r
576EFI_STATUS\r
577QNCRootPortInit (\r
578 IN UINT32 RootPortIndex,\r
579 IN PCIEXP_ROOT_PORT_CONFIGURATION *RootPortConfig,\r
580 IN UINT64 PciExpressBar,\r
581 IN UINT32 QNCRootComplexBar,\r
582 IN UINT32 QNCPmioBase,\r
583 IN UINT32 QNCGpeBase\r
584 )\r
585{\r
586 UINT64 RPBase;\r
587 UINT64 EndPointBase;\r
588 UINT64 LpcBase;\r
589 UINT16 AspmVal;\r
590 UINT16 SlotStatus;\r
591 UINTN Index;\r
592 UINT32 CapOffset;\r
593 UINT32 DwordReg;\r
594\r
595 RPBase = PciExpressBar + (((PCI_BUS_NUMBER_QNC << 8) + ((PCI_DEVICE_NUMBER_PCIE_ROOTPORT) << 3) + ((PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex) << 0)) << 12);\r
596 LpcBase = PciExpressBar + (((PCI_BUS_NUMBER_QNC << 8) + (31 << 3) + (0 << 0)) << 12);\r
597 CapOffset = PcieFindCapId (PCI_BUS_NUMBER_QNC, (UINT8)(PCI_DEVICE_NUMBER_PCIE_ROOTPORT), (UINT8)(PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex), PCIE_CAPID);\r
598\r
599 if (CapOffset == 0) {\r
600 return EFI_UNSUPPORTED;\r
601 }\r
602\r
603 //\r
604 // Initialize "Slot Implmemented Bit" for this root port\r
605 //\r
606 if (RootPortConfig[RootPortIndex].Bits.SlotImplemented) {\r
607 QNCMmio16Or (RPBase, R_QNC_PCIE_XCAP, B_QNC_PCIE_XCAP_SI);\r
608 }\r
609\r
610 //\r
611 // For Root Port Slots Numbering on the CRBs.\r
612 // Root Port 0 = Slot 1\r
613 // Root Port 1 = Slot 2\r
614 // Root Port 2 = Slot 3\r
615 // Root Port 3 = Slot 4\r
616 //\r
617 DwordReg = QNCMmio32 (RPBase, R_QNC_PCIE_SLCAP);\r
618 DwordReg &= B_QNC_PCIE_SLCAP_MASK_RSV_VALUE;\r
619 DwordReg |= (V_QNC_PCIE_SLCAP_SLV << V_QNC_PCIE_SLCAP_SLV_OFFSET);\r
620 DwordReg |= ((RootPortConfig[RootPortIndex].Bits.PhysicalSlotNumber) << V_QNC_PCIE_SLCAP_PSN_OFFSET) ;\r
621 QNCMmio32 (RPBase, R_QNC_PCIE_SLCAP) = DwordReg;\r
622\r
623 //\r
624 // Check for a Presence Detect Change.\r
625 //\r
626 SlotStatus = QNCMmio16 (RPBase, R_QNC_PCIE_SLSTS);\r
627 if ((SlotStatus & (B_QNC_PCIE_SLSTS_PDS + B_QNC_PCIE_SLSTS_PDC)) == 0) {\r
628 return EFI_NOT_FOUND;\r
629 }\r
630\r
631 //\r
632 // Temporarily Hardcode the Root Port Bridge Number to 2.\r
633 //\r
634 // This Endpoint check should immediately pass. Howerver, a 900ms delay\r
635 // has been added to match the timing requirements of the PCI Express Base\r
636 // Specification, Revision 1.0A, Section 6.6 ("...software must allow 1.0s\r
637 // after a reset of a device, before it may determine that a device which\r
638 // fails to return a Successful Completion status for a valid Configuration\r
639 // Request is a broken device"). Note that a 100ms delay was already added\r
640 // after the Root Ports were first taken out of reset.\r
641 //\r
642 QNCMmio32AndThenOr (RPBase, R_QNC_PCIE_BNUM, 0xFF0000FF, 0x00020200);\r
643 //\r
644 // Only do this when a downstream device is present\r
645 //\r
646 EndPointBase = PciExpressBar + (((2 << 8) + (0 << 3) + (0 << 0)) << 12);\r
647 if ((SlotStatus & B_QNC_PCIE_SLSTS_PDS) != 0) {\r
648 for (Index = 0; Index < V_PCIE_MAX_TRY_TIMES; Index++){\r
649 if (QNCMmio16 (EndPointBase, 0x0) != 0xFFFF) {\r
650 break;\r
651 }\r
652 PcieStall (15);\r
653 }\r
654 if (Index >= V_PCIE_MAX_TRY_TIMES) {\r
655 //\r
656 // Clear Bus Numbers.\r
657 //\r
658 QNCMmio32And (RPBase, R_QNC_PCIE_BNUM, 0xFF0000FF);\r
659 return EFI_NOT_FOUND;\r
660 }\r
661 }\r
662\r
663 //\r
664 // PCI Express* Virtual Channels\r
665 // Clear TC1-7 Traffic classes.\r
666 // Map TC0-VC0\r
667 //\r
668 PcieInitTcxVc0 (PCI_BUS_NUMBER_QNC, (UINT8)(PCI_DEVICE_NUMBER_PCIE_ROOTPORT), (UINT8)(PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex), 2, 0, 0);\r
669 PcieMapTcxVc0 (PCI_BUS_NUMBER_QNC, (UINT8)(PCI_DEVICE_NUMBER_PCIE_ROOTPORT), (UINT8)(PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex), 2, 0, 0, 0x0);\r
670\r
671 //\r
672 // Set Common Clock for inserted cards\r
673 //\r
674 if ((SlotStatus & B_QNC_PCIE_SLSTS_PDS) != 0) {\r
675 PcieSetCommonClock (PCI_BUS_NUMBER_QNC, (UINT8)(PCI_DEVICE_NUMBER_PCIE_ROOTPORT), (UINT8)(PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex), 2, 0);\r
676 }\r
677\r
678 //\r
679 // Flow for Enabling ASPM\r
680 //\r
681 if (RootPortConfig[RootPortIndex].Bits.AspmEnable) {\r
682 if (RootPortConfig[RootPortIndex].Bits.AspmAutoEnable) {\r
683 PcieSetAspmAuto (PCI_BUS_NUMBER_QNC, (UINT8)(PCI_DEVICE_NUMBER_PCIE_ROOTPORT), (UINT8)(PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex), 2, 0, 0, &AspmVal);\r
684 } else {\r
685 //\r
686 // Set ASPM values according to setup selections, masked by capabilities\r
687 //\r
688 PcieSetAspmManual (\r
689 PCI_BUS_NUMBER_QNC,\r
690 (UINT8) (PCI_DEVICE_NUMBER_PCIE_ROOTPORT),\r
691 (UINT8) (PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex),\r
692 (UINT8) ((RootPortConfig[RootPortIndex].Bits.AspmL0sEnable & 0x01) | (RootPortConfig[RootPortIndex].Bits.AspmL1Enable << 1)),\r
693 &AspmVal\r
694 );\r
695 }\r
696 }\r
697\r
698 //\r
699 // Enable the PCIe CLKREQ#\r
700 //\r
701 if ((SlotStatus & B_QNC_PCIE_SLSTS_PDS) != 0) {\r
702 PcieSetClkreq (2, 0);\r
703 }\r
704\r
705 //\r
706 // Clear Bus Numbers\r
707 //\r
708 QNCMmio32And (RPBase, R_QNC_PCIE_BNUM, 0xFF0000FF);\r
709\r
710 //\r
711 // Additional configurations\r
712 //\r
713\r
714 //\r
715 // PCI-E Unsupported Request Reporting Enable\r
716 //\r
717 if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_URE_ENABLE) {\r
718 QNCMmio16Or (RPBase, R_QNC_PCIE_DCTL, B_QNC_PCIE_DCTL_URE);\r
719 }\r
720\r
721 //\r
722 // Device Fatal Error Reporting Enable\r
723 //\r
724 if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_FEE_ENABLE) {\r
725 QNCMmio16Or (RPBase, R_QNC_PCIE_DCTL, B_QNC_PCIE_DCTL_FEE);\r
726 }\r
727\r
728 //\r
729 // Device Non Fatal Error Reporting Enable\r
730 //\r
731 if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_NFE_ENABLE) {\r
732 QNCMmio16Or (RPBase, R_QNC_PCIE_DCTL, B_QNC_PCIE_DCTL_NFE);\r
733 }\r
734\r
735 //\r
736 // Device Correctable Error Reporting Enable\r
737 //\r
738 if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_CEE_ENABLE) {\r
739 QNCMmio16Or (RPBase, R_QNC_PCIE_DCTL, B_QNC_PCIE_DCTL_CEE);\r
740 }\r
741 //\r
742 // Root PCI-E PME Interrupt Enable\r
743 //\r
744 if (RootPortConfig[RootPortIndex].Bits.PmeInterruptEnable) {\r
745 QNCMmio16Or (RPBase, R_QNC_PCIE_RCTL, B_QNC_PCIE_RCTL_PIE);\r
746 }\r
747 //\r
748 // Root PCI-E System Error on Fatal Error Enable\r
749 //\r
750 if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_SFE_ENABLE) {\r
751 QNCMmio16Or (RPBase, R_QNC_PCIE_RCTL, B_QNC_PCIE_RCTL_SFE);\r
752 }\r
753\r
754 //\r
755 // Root PCI-E System Error on Non-Fatal Error Enable\r
756 //\r
757 if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_SNE_ENABLE) {\r
758 QNCMmio16Or (RPBase, R_QNC_PCIE_RCTL, B_QNC_PCIE_RCTL_SNE);\r
759 }\r
760\r
761 //\r
762 // Root PCI-E System Error on Correctable Error Enable\r
763 //\r
764 if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_SCE_ENABLE) {\r
765 QNCMmio16Or (RPBase, R_QNC_PCIE_RCTL, B_QNC_PCIE_RCTL_SCE);\r
766 }\r
767\r
768 //\r
769 // Root PCI-E Powermanagement SCI Enabled\r
770 //\r
771 if (RootPortConfig[RootPortIndex].Bits.PmSciEnable) {\r
772 //\r
773 // Make sure that PME Interrupt Enable bit of Root Control register\r
774 // of PCI Express Capability struceture is cleared\r
775 //\r
776 QNCMmio32And (RPBase, R_QNC_PCIE_RCTL, (~B_QNC_PCIE_RCTL_PIE));\r
777 QNCMmio32AndThenOr (RPBase, R_QNC_PCIE_MPC, (~B_QNC_PCIE_MPC_PMME), B_QNC_PCIE_MPC_PMCE);\r
778\r
779 //\r
780 // Make sure GPE0 Stutus RW1C Bit is clear.\r
781 //\r
782 DwordReg = IoRead32 (QNCGpeBase + R_QNC_GPE0BLK_GPE0S);\r
783 if ((DwordReg & B_QNC_GPE0BLK_GPE0S_PCIE) != 0) {\r
784 IoWrite32 (QNCGpeBase + R_QNC_GPE0BLK_GPE0S, B_QNC_GPE0BLK_GPE0S_PCIE);\r
785 }\r
786 }\r
787\r
788 //\r
789 // PCIe Hot Plug SCI Enable\r
790 //\r
791 if (RootPortConfig[RootPortIndex].Bits.HotplugSciEnable) {\r
792 //\r
793 // Write clear for :\r
794 // Attention Button Pressed (bit0)\r
795 // Presence Detect Changed (bit3)\r
796 //\r
797 QNCMmio32Or (RPBase, R_QNC_PCIE_SLSTS, (B_QNC_PCIE_SLSTS_PDC | B_QNC_PCIE_SLSTS_ABP));\r
798\r
799 //\r
800 // Sequence 2: Program the following bits in Slot Control register at offset 18h\r
801 // of PCI Express* Capability structure:\r
802 // Attention Button Pressed Enable (bit0) = 1b\r
803 // Presence Detect Changed Enable (bit3) = 1b\r
804 // Hot Plug Interrupt Enable (bit5) = 0b\r
805 //\r
806 QNCMmio32AndThenOr (RPBase, R_QNC_PCIE_SLCTL, (~B_QNC_PCIE_SLCTL_HPE), (B_QNC_PCIE_SLCTL_PDE | B_QNC_PCIE_SLCTL_ABE));\r
807\r
808 //\r
809 // Sequence 3: Program Misc Port Config (MPC) register at PCI config space offset\r
810 // D8h as follows:\r
811 // Hot Plug SCI Enable (HPCE, bit30) = 1b\r
812 // Hot Plug SMI Enable (HPME, bit1) = 0b\r
813 //\r
814 QNCMmio32AndThenOr (RPBase, R_QNC_PCIE_MPC, (~B_QNC_PCIE_MPC_HPME), B_QNC_PCIE_MPC_HPCE);\r
815 }\r
816\r
817\r
818 return EFI_SUCCESS;\r
819}\r
820\r
821\r
822/**\r
823 Perform Initialization of the Downstream Root Ports\r
824**/\r
825VOID\r
826QNCDownStreamPortsInit (\r
827 IN PCIEXP_ROOT_PORT_CONFIGURATION *RootPortConfig,\r
828 IN QNC_DEVICE_ENABLES *QNCDeviceEnables,\r
829 IN UINT64 PciExpressBar,\r
830 IN UINT32 QNCRootComplexBar,\r
831 IN UINT32 QNCPmioBase,\r
832 IN UINT32 QNCGpeBase,\r
833 OUT UINTN *RpEnableMask\r
834 )\r
835{\r
836 EFI_STATUS Status;\r
837 UINT32 Index;\r
838\r
839 //\r
840 // Initialize every root port and downstream device\r
841 //\r
842 for (Index = 0;Index < MAX_PCI_EXPRESS_ROOT_PORTS;Index++) {\r
843 if ((QNCDeviceEnables->Uint32 & (1 << Index)) != 0) {\r
844 Status = QNCRootPortInit (\r
845 Index,\r
846 RootPortConfig,\r
847 PciExpressBar,\r
848 QNCRootComplexBar,\r
849 QNCPmioBase,\r
850 QNCGpeBase\r
851 );\r
852\r
853 if (!EFI_ERROR (Status)) {\r
854 (*RpEnableMask) |= LShiftU64(1, Index);\r
855 DEBUG ((EFI_D_INFO, " Root Port %x device found, enabled. RpEnableMask: 0x%x\n", Index + 1, *RpEnableMask));\r
856 }\r
857 }\r
858 }\r
859}\r
860\r
861/**\r
862 Do early init of pci express rootports on Soc.\r
863\r
864**/\r
865\r
866VOID\r
867EFIAPI\r
868PciExpressEarlyInit (\r
869 VOID\r
870 )\r
871{\r
872 //\r
873 // Setup Message Bus Idle Counter (SBIC) values.\r
874 //\r
875 QNCMmPci8(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_IOSFSBCTL) = QNCMmPci8AndThenOr(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_IOSFSBCTL, (~B_QNC_PCIE_IOSFSBCTL_SBIC_MASK), V_PCIE_ROOT_PORT_SBIC_VALUE);\r
876 QNCMmPci8(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1, R_QNC_PCIE_IOSFSBCTL) = QNCMmPci8AndThenOr(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1, R_QNC_PCIE_IOSFSBCTL, (~B_QNC_PCIE_IOSFSBCTL_SBIC_MASK), V_PCIE_ROOT_PORT_SBIC_VALUE);\r
877\r
878 //\r
879 // Program SVID/SID the same as VID/DID for Root ports.\r
880 //\r
881 QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_SVID) = QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, PCI_VENDOR_ID_OFFSET);\r
882 QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1, R_QNC_PCIE_SVID) = QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1, PCI_VENDOR_ID_OFFSET);\r
883\r
884 //\r
885 // Set the IPF bit in MCR2\r
886 //\r
887 QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_MPC2) = QNCMmPci32Or(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_MPC2, B_QNC_PCIE_MPC2_IPF);\r
888 QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1, R_QNC_PCIE_MPC2) = QNCMmPci32Or(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1, R_QNC_PCIE_MPC2, B_QNC_PCIE_MPC2_IPF);\r
889\r
890 //\r
891 // Set up the Posted and Non Posted Request sizes for PCIe\r
892 //\r
893 QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_CCFG) = QNCMmPci32AndThenOr(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_CCFG, ~B_QNC_PCIE_CCFG_UPSD, (B_QNC_PCIE_CCFG_UNRS | B_QNC_PCIE_CCFG_UPRS));\r
894\r
895 return;\r
896}\r
897\r
898\r
899/**\r
900 Complete initialization all the pci express rootports on Soc.\r
901**/\r
902EFI_STATUS\r
903EFIAPI\r
904PciExpressInit (\r
905 )\r
906{\r
907 UINT64 PciExpressBar;\r
908 UINT32 QNCRootComplexBar;\r
909 UINT32 QNCGpioBase;\r
910 UINT32 QNCPmioBase;\r
911 UINT32 QNCGpeBase;\r
912 UINTN RpEnableMask;\r
913 PCIEXP_ROOT_PORT_CONFIGURATION *mRootPortConfig;\r
914 QNC_DEVICE_ENABLES mQNCDeviceEnables;\r
915\r
916 //\r
917 // Get BAR registers\r
918 //\r
919 QNCRootComplexBar = QNC_RCRB_BASE;\r
920 QNCGpioBase = LpcPciCfg32 (R_QNC_LPC_GBA_BASE) & B_QNC_LPC_GPA_BASE_MASK;\r
921 QNCPmioBase = LpcPciCfg32 (R_QNC_LPC_PM1BLK) & B_QNC_LPC_PM1BLK_MASK;\r
922 QNCGpeBase = LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & B_QNC_LPC_GPE0BLK_MASK;\r
923 RpEnableMask = 0; // assume all root ports are disabled\r
924\r
925 PciExpressBar = PcdGet64 (PcdPciExpressBaseAddress);\r
926\r
927 //\r
928 // Get platform information from PCD entries\r
929 //\r
930 mQNCDeviceEnables.Uint32 = PcdGet32 (PcdDeviceEnables);\r
931 mRootPortConfig = (PCIEXP_ROOT_PORT_CONFIGURATION*) PcdGetPtr (PcdPcieRootPortConfiguration);\r
932\r
933 DEBUG ((EFI_D_INFO, " mRootPortConfig: 0x%x, value1: 0x%x, value2: 0x%x, value3: 0x%x, value4: 0x%x\n",\r
934 mRootPortConfig, mRootPortConfig[0].Uint32, mRootPortConfig[1].Uint32,\r
935 mRootPortConfig[2].Uint32, mRootPortConfig[3].Uint32));\r
936\r
937 QNCDownStreamPortsInit (\r
938 mRootPortConfig,\r
939 &mQNCDeviceEnables,\r
940 PciExpressBar,\r
941 QNCRootComplexBar,\r
942 QNCPmioBase,\r
943 QNCGpeBase,\r
944 &RpEnableMask\r
945 );\r
946\r
947 return EFI_SUCCESS;\r
948}\r
949\r