linker script: hax :/
[coreboot.git] / src / vendorcode / amd / cimx / sb900 / Gpp.c
1
2 /**
3  * @file
4  *
5  * Config Southbridge GPP controller
6  *
7  * Init GPP features.
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project:      CIMx-SB
11  * @e sub-project
12  * @e \$Revision:$   @e \$Date:$
13  *
14  */
15 /*
16 *****************************************************************************
17 *
18 * Copyright (c) 2011, Advanced Micro Devices, Inc.
19 * All rights reserved.
20
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions are met:
23 *     * Redistributions of source code must retain the above copyright
24 *       notice, this list of conditions and the following disclaimer.
25 *     * Redistributions in binary form must reproduce the above copyright
26 *       notice, this list of conditions and the following disclaimer in the
27 *       documentation and/or other materials provided with the distribution.
28 *     * Neither the name of Advanced Micro Devices, Inc. nor the names of 
29 *       its contributors may be used to endorse or promote products derived 
30 *       from this software without specific prior written permission.
31
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
36 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
39 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42
43 ****************************************************************************
44 */
45 #include "SbPlatform.h"
46 #include "cbtypes.h"
47 #include "AmdSbLib.h"
48
49 /**
50  * PCIE_CAP_ID - PCIe Cap ID
51  *
52  */
53 #define  PCIE_CAP_ID             0x10
54
55 //
56 // Declaration of local functions
57 //
58 UINT8
59 sbFindPciCap (
60   IN       UINT32  pciAddress,
61   IN       UINT8  targetCapId
62   );
63
64 VOID
65 sbGppSetAspm (
66   IN       UINT32    pciAddress,
67   IN       UINT8     LxState
68   );
69
70 VOID
71 sbGppSetEPAspm (
72   IN       UINT32    pciAddress,
73   IN       UINT8     LxState
74   );
75
76 VOID
77 sbGppValidateAspm (
78   IN       UINT32    pciAddress,
79   IN       UINT8     *LxState
80   );
81
82 VOID
83 sbGppForceGen2 (
84   IN       AMDSBCFG        *pConfig,
85   IN       CONST UINT8     ActivePorts
86   );
87
88 VOID
89 sbGppForceGen1 (
90   IN       AMDSBCFG      *pConfig,
91   IN       CONST UINT8   ActivePorts
92   );
93
94 VOID
95 PreInitGppLink (
96   IN       AMDSBCFG* pConfig
97   );
98
99 UINT8
100 GppPortPollingLtssm (
101   IN       AMDSBCFG*      pConfig,
102   IN       UINT8          ActivePorts,
103   IN       BOOLEAN        IsGen2
104   );
105
106 UINT8
107 CheckGppLinkStatus (
108   IN       AMDSBCFG* pConfig
109   );
110
111 VOID
112 AfterGppLinkInit (
113   IN       AMDSBCFG* pConfig
114   );
115
116 VOID
117 sbGppDynamicPowerSaving (
118   IN       AMDSBCFG* pConfig
119   );
120
121 VOID
122 sbGppAerInitialization (
123   IN       AMDSBCFG* pConfig
124   );
125
126 VOID
127 sbGppRasInitialization (
128   IN     AMDSBCFG*   pConfig
129   );
130
131 //
132 // Declaration of external functions
133 //
134
135
136 /**
137  * sbFindPciCap - Find PCI Cap
138  *
139  *
140  * @param[in] pciAddress     PCI Address.
141  * @param[in] targetCapId    Target Cap ID.
142  *
143  */
144 UINT8
145 sbFindPciCap (
146   IN       UINT32  pciAddress,
147   IN       UINT8  targetCapId
148   )
149 {
150   UINT8       NextCapPtr;
151   UINT8       CapId;
152
153   NextCapPtr = 0x34;
154   while (NextCapPtr != 0) {
155     ReadPCI (pciAddress + NextCapPtr, AccWidthUint8, &NextCapPtr);
156     if (NextCapPtr == 0xff) {
157       return 0;
158     }
159     if (NextCapPtr != 0) {
160       ReadPCI (pciAddress + NextCapPtr, AccWidthUint8, &CapId);
161       if (CapId == targetCapId) {
162         break;
163       } else {
164         NextCapPtr++;
165       }
166     }
167   }
168   return NextCapPtr;
169 }
170
171 /**
172  * sbGppSetAspm - Set GPP ASPM
173  *
174  *
175  * @param[in] pciAddress PCI Address.
176  * @param[in] LxState    Lane State.
177  *
178  */
179 VOID
180 sbGppSetAspm (
181   IN       UINT32    pciAddress,
182   IN       UINT8     LxState
183   )
184 {
185   UINT8      pcieCapOffset;
186   UINT8      value8;
187
188   pcieCapOffset = sbFindPciCap (pciAddress, PCIE_CAP_ID);
189   if (pcieCapOffset) {
190     // Read link capabilities register (0x0C[11:10] - ASPM support)
191     ReadPCI (pciAddress + pcieCapOffset + 0x0D, AccWidthUint8, &value8);
192     if (value8 & BIT2) {
193       value8 = (value8 >> 2) & (BIT1 + BIT0);
194       // Set ASPM state in link control register
195       RWPCI (pciAddress + pcieCapOffset + 0x10, AccWidthUint8, 0xffffffff, LxState & value8);
196     }
197   }
198 }
199
200 /**
201  * sbGppSetEPAspm - Set EP GPP ASPM
202  *
203  *
204  * @param[in] pciAddress PCI Address.
205  * @param[in] LxState    Lane State.
206  *
207  */
208 VOID
209 sbGppSetEPAspm (
210   IN       UINT32    pciAddress,
211   IN       UINT8     LxState
212   )
213 {
214   UINT8      value8;
215   UINT8      maxFuncs;
216   UINT32     devBDF;
217
218   maxFuncs = 1;
219   ReadPCI (pciAddress + 0x0E, AccWidthUint8, &value8);
220
221   if (value8 & BIT7) {
222     maxFuncs = 8;              // multi-function device
223   }
224   while (maxFuncs != 0) {
225     devBDF = pciAddress + (UINT32) ((maxFuncs - 1) << 16);
226     sbGppSetAspm (devBDF, LxState);
227     maxFuncs--;
228   }
229 }
230
231 /**
232  * sbGppValidateAspm - Validate endpoint support for GPP ASPM
233  *
234  *
235  * @param[in] pciAddress PCI Address.
236  * @param[in] LxState    Lane State.
237  *
238  */
239 VOID
240 sbGppValidateAspm (
241   IN       UINT32    pciAddress,
242   IN       UINT8     *LxState
243   )
244 {
245   UINT8      pcieCapOffset;
246   UINT8      value8;
247   UINT8      maxFuncs;
248   UINT32     devBDF;
249
250   maxFuncs = 1;
251   ReadPCI (pciAddress + 0x0E, AccWidthUint8, &value8);
252
253   if (value8 & BIT7) {
254     maxFuncs = 8;              // multi-function device
255   }
256   while (maxFuncs != 0) {
257     devBDF = pciAddress + (UINT32) ((maxFuncs - 1) << 16);
258     pcieCapOffset = sbFindPciCap (devBDF, PCIE_CAP_ID);
259     if (pcieCapOffset) {
260       // Read link capabilities register (0x0C[11:10] - ASPM support)
261       ReadPCI (devBDF + pcieCapOffset + 0x0D, AccWidthUint8, &value8);
262       if (value8 & BIT2) {
263         value8 = (value8 >> 2) & (BIT1 + BIT0);
264         // Set ASPM state as what's endpoint support
265         *LxState &= value8;
266       }
267     }
268     maxFuncs--;
269   }
270 }
271
272
273 /**
274  * sbGppForceGen2 - Set GPP to Gen2
275  *
276  *
277  * @param[in] pConfig Southbridge configuration structure pointer.
278  * @param[in] ActivePorts Activate Ports.
279  *
280  */
281 VOID
282 sbGppForceGen2 (
283   IN       AMDSBCFG        *pConfig,
284   IN       CONST UINT8     ActivePorts
285   )
286 {
287   UINT32       portId;
288
289   for ( portId = 0; portId < MAX_GPP_PORTS; portId++ ) {
290     if (ActivePorts & (1 << portId)) {
291       rwAlink (SB_RCINDXP_REGA4 | portId << 24, 0xFFFFFFFF, BIT29 + BIT0);
292       rwAlink ((SB_ABCFG_REG340 + portId * 4) | (UINT32) (ABCFG << 29), 0xFFFFFFFF, BIT21);
293       rwAlink (SB_RCINDXP_REGA2 | portId << 24, ~BIT13, 0);
294       rwAlink (SB_RCINDXP_REGC0 | portId << 24, ~BIT15, 0);
295       RWPCI (PCI_ADDRESS (0, GPP_DEV_NUM, portId, 0x88), AccWidthUint8, 0xf0, 0x02);
296
297       (&pConfig->PORTCONFIG[portId].PortCfg)->PortIsGen2 = 2;
298     }
299   }
300 }
301
302 /**
303  * sbGppForceGen1 - Set GPP to Gen1
304  *
305  *
306  * @param[in] pConfig Southbridge configuration structure pointer.
307  * @param[in] ActivePorts Activate Ports.
308  *
309  */
310 VOID
311 sbGppForceGen1 (
312   IN       AMDSBCFG      *pConfig,
313   IN       CONST UINT8   ActivePorts
314   )
315 {
316   UINT32       portId;
317
318   for ( portId = 0; portId < MAX_GPP_PORTS; portId++ ) {
319     if (ActivePorts & (1 << portId) && pConfig->GppHardwareDowngrade != portId + 1) {
320       rwAlink ((SB_ABCFG_REG340 + portId * 4) | (UINT32) (ABCFG << 29), ~BIT21, 0);
321       rwAlink (SB_RCINDXP_REGA4 | portId << 24, ~BIT0, BIT29);
322       rwAlink (SB_RCINDXP_REGA2 | portId << 24, 0xFFFFFFFF, BIT13);
323       rwAlink (SB_RCINDXP_REGC0 | portId << 24, ~BIT15, 0);
324       RWPCI (PCI_ADDRESS (0, GPP_DEV_NUM, portId, 0x88), AccWidthUint8, 0xf0, 0x01);
325
326       (&pConfig->PORTCONFIG[portId].PortCfg)->PortIsGen2 = 1;
327     }
328   }
329 }
330
331
332 /**
333  * PreInitGppLink - Enable GPP link training.
334  *
335  *
336  *
337  * @param[in] pConfig Southbridge configuration structure pointer.
338  *
339  */
340 VOID
341 PreInitGppLink (
342   IN       AMDSBCFG* pConfig
343   )
344 {
345   UINT8 portMask[5] = {
346     0x01,
347     0x00,
348     0x03,
349     0x07,
350     0x0F
351   };
352   UINT8  cfgMode;
353   UINT8  portId;
354   UINT32 reg32Value;
355   UINT16 tmp16Value;
356
357 //  PCIE_GPP_ENABLE (abcfg:0xC0):
358 //
359 //     GPP_LINK_CONFIG ([3:0])  PortA   PortB   PortC   PortD    Description
360 //    ----------------------------------------------------------------------------------
361 //                       0000    0-3                             x4 Config
362 //                       0001                                    N/A
363 //                       0010    0-1     2-3      0              2:2 Config
364 //                       0011    0-1      2       3              2:1:1 Config
365 //                       0100     0       1       2       3      1:1:1:1 Config
366 //
367 //  For A12 and above:
368 //                  ABCFG:0xC0[12] - Port A hold training (default 1)
369 //                  ABCFG:0xC0[13] - Port B hold training (default 1)
370 //                  ABCFG:0xC0[14] - Port C hold training (default 1)
371 //                  ABCFG:0xC0[15] - Port D hold training (default 1)
372 //
373 //
374   //
375   // Set port enable bit fields based on current GPP link configuration mode
376   //
377   cfgMode = (UINT8) pConfig->GppLinkConfig;
378   if ( cfgMode > GPP_CFGMODE_X1111 || cfgMode == 1 ) {
379     cfgMode = GPP_CFGMODE_X4000;
380     pConfig->GppLinkConfig = GPP_CFGMODE_X4000;
381   }
382   reg32Value = (UINT32) portMask[cfgMode];
383
384   // Mask out non-applicable ports according to the target link configuration mode
385   for ( portId = 0; portId < MAX_GPP_PORTS; portId++ ) {
386     pConfig->PORTCONFIG[portId].PortCfg.PortPresent &= (reg32Value >> portId) & BIT0;
387   }
388
389   //
390   // Deassert GPP reset and pull EP out of reset - Clear GPP_RESET (abcfg:0xC0[8] = 0)
391   //
392   tmp16Value = (UINT16) (~reg32Value << 12);
393   reg32Value = (UINT32) (tmp16Value + (reg32Value << 4) + cfgMode);
394   writeAlink (SB_ABCFG_REGC0 | (UINT32) (ABCFG << 29), reg32Value);
395
396   reg32Value = readAlink (0xC0 | (UINT32) (RCINDXC << 29));
397   writeAlink (0xC0 | (UINT32) (RCINDXC << 29), reg32Value | 0x400);  // Set STRAP_F0_MSI_EN
398
399   // A-Link L1 Entry Delay Shortening
400   // AXINDP_Reg 0xA0[7:4] = 0x3
401   rwAlink (SB_AX_INDXP_REGA0, 0xFFFFFF0F, 0x30);
402   rwAlink (SB_AX_INDXP_REGB1, 0xFFFFFFFF, BIT19);
403   rwAlink (SB_AX_INDXP_REGB1, 0xFFFFFFFF, BIT28);
404
405   // RPR5.22 GPP L1 Entry Delay Shortening
406   // RCINDP_Reg 0xA0[7:4] = 0x1 Enter L1 sooner after ACK'ing PM request.
407   // This is done to reduce number of NAK received with L1 enabled.
408   // ENH254401: Program L0S/L1 activity timer to enable L0S/L1 on GPP
409   // RCINDP_Reg 0xA0[11:8] = 0x9
410   // RCINDP_Reg 0xA0[15:12] = 0x6
411   for ( portId = 0; portId < MAX_GPP_PORTS; portId++ ) {
412     rwAlink (SB_RCINDXP_REGA0 | portId << 24, 0xFFFF000F, 0x6910);
413     //OBS220313: Hard System Hang running MeatGrinder Test on multiple blocks
414     //RPR 5.13 GPP Error Reporting Configuration
415     rwAlink (SB_RCINDXP_REG6A | portId << 24, ~(BIT1), 0);
416   }
417
418   if (pConfig->S3Resume) {
419     SBGPPPORTCONFIG  *portCfg;
420
421     for ( portId = 0; portId < MAX_GPP_PORTS; portId++ ) {
422       portCfg = &pConfig->PORTCONFIG[portId].PortCfg;
423       if (portCfg->PortHotPlug == TRUE) {
424         portCfg->PortDetected = FALSE;
425       } else {
426         if (portCfg->PortIsGen2 == 1) {
427           sbGppForceGen1 (pConfig, (UINT8) (1 << portId));
428         } else {
429           sbGppForceGen2 (pConfig, (UINT8) (1 << portId));
430         }
431       }
432     }
433   }
434
435   // Obtain original Gen2 strap value (LC_GEN2_EN_STRAP)
436   pConfig->GppGen2Strap = (UINT8) (readAlink (SB_RCINDXP_REGA4 | 0 << 24) & BIT0);
437 }
438
439
440 /**
441  * GppPortPollingLtssm - Loop polling the LTSSM for each GPP port marked in PortMap
442  *
443  *
444  * Return:     FailedPortMap   = A bitmap of ports which failed to train
445  *
446  * @param[in]    pConfig      Southbridge configuration structure pointer.
447  * @param[in]    ActivePorts  A bitmap of ports which should be polled
448  * @param[in]    IsGen2       TRUE if the polling is in Gen2 mode
449  *
450  */
451 UINT8
452 GppPortPollingLtssm (
453   IN       AMDSBCFG*      pConfig,
454   IN       UINT8          ActivePorts,
455   IN       BOOLEAN        IsGen2
456   )
457 {
458   UINT32            retryCounter;
459   UINT8             PortId;
460   UINT8             FailedPorts;
461   SBGPPPORTCONFIG  *portCfg;
462   UINT32            abIndex;
463   UINT32            Data32;
464   UINT8             EmptyPorts;
465
466   FailedPorts = 0;
467   retryCounter = MAX_LT_POLLINGS;
468   EmptyPorts = ActivePorts;
469
470   while (retryCounter-- && ActivePorts) {
471     for (PortId = 0; PortId < MAX_GPP_PORTS; PortId++) {
472       if (ActivePorts & (1 << PortId)) {
473         portCfg = &pConfig->PORTCONFIG[PortId].PortCfg;
474         abIndex = SB_RCINDXP_REGA5 | (UINT32) (RCINDXP << 29) | (PortId << 24);
475         Data32 = readAlink (abIndex) & 0x3F3F3F3F;
476
477         if ((UINT8) (Data32) > 0x04) {
478           EmptyPorts &= ~(1 << PortId);
479         }
480
481         if ((UINT8) (Data32) == 0x10) {
482           ActivePorts &= ~(1 << PortId);
483           portCfg->PortDetected = TRUE;
484           break;
485         }
486         if (IsGen2) {
487           UINT8      i;
488
489           for (i = 0; i < 4; i++) {
490             if ((UINT8) (Data32) == 0x29 || (UINT8) (Data32) == 0x2A ) {
491               ActivePorts &= ~(1 << PortId);
492               FailedPorts |= (1 << PortId);
493               break;
494             }
495             Data32 >>= 8;
496           }
497         }
498       }
499     }
500     if (EmptyPorts && retryCounter < (MAX_LT_POLLINGS - 200)) {
501       ActivePorts &= ~EmptyPorts;
502     }
503     SbStall (1000);
504   }
505   FailedPorts |= ActivePorts;
506   return FailedPorts;
507 }
508
509
510 /**
511  * CheckGppLinkStatus - loop polling the link status for each GPP port
512  *
513  *
514  * Return:     ToggleStatus[3:0] = Port bitmap for those need to clear De-emphasis
515  *
516  * @param[in] pConfig Southbridge configuration structure pointer.
517  *
518  */
519 UINT8
520 CheckGppLinkStatus (
521   IN       AMDSBCFG* pConfig
522   )
523 {
524   UINT32            portId;
525   UINT8             portScanMap;
526   UINT8             GppHwDowngrade;
527   SBGPPPORTCONFIG  *portCfg;
528   UINT8             FailedPorts;
529
530
531   portScanMap = 0;
532   FailedPorts = 0;
533
534   // Obtain a list of ports to be checked
535   for ( portId = 0; portId < MAX_GPP_PORTS; portId++ ) {
536     portCfg = &pConfig->PORTCONFIG[portId].PortCfg;
537     if ( portCfg->PortPresent == TRUE && portCfg->PortDetected == FALSE ) {
538       portScanMap |= 1 << portId;
539     }
540   }
541   GppHwDowngrade = (UINT8)pConfig->GppHardwareDowngrade;
542   if (GppHwDowngrade != 0) {
543     // Skip polling and always assume this port to be present
544     portScanMap &= ~(1 << (GppHwDowngrade - 1));
545   }
546
547   //GPP Gen2 Speed Change
548   // if ((GPP Gen2 == enabled) and (RCINDP_Reg 0xA4[0] == 0x1)) {
549   //   PCIe_Cfg 0x88[3:0]  = 0x2
550   //   RCINDP_Reg 0xA2[13] = 0x0
551   //   RCINDP_Reg 0xC0[15] = 0x0
552   //   RCINDP_Reg 0xA4[29] = 0x1
553   // } else {
554   //   PCIe_Cfg 0x88[3:0]  = 0x1
555   //   RCINDP_Reg 0xA4[0]  = 0x0
556   //   RCINDP_Reg 0xA2[13] = 0x1
557   //   RCINDP_Reg 0xC0[15] = 0x0
558   //   RCINDP_Reg 0xA4[29] = 0x1
559   // }
560   SbStall (5000);
561   if (pConfig->GppGen2 && pConfig->GppGen2Strap) {
562     sbGppForceGen2 (pConfig, portScanMap);
563     FailedPorts = GppPortPollingLtssm (pConfig, portScanMap, TRUE);
564
565     if (FailedPorts) {
566       sbGppForceGen1 (pConfig, FailedPorts);
567       FailedPorts = GppPortPollingLtssm (pConfig, FailedPorts, FALSE);
568     }
569   } else {
570     sbGppForceGen1 (pConfig, portScanMap);
571     FailedPorts = GppPortPollingLtssm (pConfig, portScanMap, FALSE);
572   }
573   return FailedPorts;
574 }
575
576
577 /**
578  * AfterGppLinkInit
579  *       - Search for display device behind each GPP port
580  *       - If the port is empty AND not hotplug-capable:
581  *           * Turn off link training
582  *           * (optional) Power down the port
583  *           * Hide the configuration space (Turn off the port)
584  *
585  * @param[in] pConfig Southbridge configuration structure pointer.
586  *
587  */
588 VOID
589 AfterGppLinkInit (
590   IN       AMDSBCFG* pConfig
591   )
592 {
593   UINT32           portId;
594   SBGPPPORTCONFIG  *portCfg;
595   UINT32           regBusNumber;
596   UINT32           abValue;
597   UINT32           abIndex;
598   UINT8            bValue;
599   UINT8            cimGppGen2;
600
601   cimGppGen2 = pConfig->GppGen2;
602 #if  SB_CIMx_PARAMETER == 0
603   cimGppGen2 = cimGppGen2Default;
604 #endif
605
606   pConfig->GppFoundGfxDev = 0;
607   abValue = readAlink (SB_ABCFG_REGC0 | (UINT32) (ABCFG << 29));
608   //RPR 5.9 Link Bandwidth Notification Capability Enable
609   //RCINDC:0xC1[0] = 1
610   rwAlink (SB_RCINDXC_REGC1, 0xFFFFFFFF, BIT0);
611
612   for ( portId = 0; portId < MAX_GPP_PORTS; portId++ ) {
613     // Program requester ID for every port
614     abIndex = SB_RCINDXP_REG21 | (UINT32) (RCINDXP << 29) | (portId << 24);
615     writeAlink (abIndex, (SB_GPP_DEV << 3) + portId);
616
617     //RPR 5.9 Link Bandwidth Notification Capability Enable
618     //PCIe Cfg 0x68[10] = 0
619     //PCIe Cfg 0x68[11] = 0
620     RWPCI (PCI_ADDRESS (0, GPP_DEV_NUM, portId, 0x68), AccWidthUint16, ~(BIT10 + BIT11), 0);
621
622     portCfg = &pConfig->PORTCONFIG[portId].PortCfg;
623     // Check if there is GFX device behind each GPP port
624     if ( portCfg->PortDetected == TRUE ) {
625       regBusNumber = (SBTEMP_BUS << 16) + (SBTEMP_BUS << 8);
626       WritePCI (PCI_ADDRESS (0, GPP_DEV_NUM, portId, 0x18), AccWidthUint32, &regBusNumber);
627       // *** Stall ();
628       ReadPCI (PCI_ADDRESS (SBTEMP_BUS, 0, 0, 0x0B), AccWidthUint8, &bValue);
629       if ( bValue == 3 ) {
630         pConfig->GppFoundGfxDev |= (1 << portId);
631       }
632       regBusNumber = 0;
633       WritePCI (PCI_ADDRESS (0, GPP_DEV_NUM, portId, 0x18), AccWidthUint32, &regBusNumber);
634     } else if ( portCfg->PortPresent == FALSE || portCfg->PortHotPlug == FALSE ) {
635       // Mask off non-applicable ports
636       abValue &= ~(1 << (portId + 4));
637     }
638
639     if ( portCfg->PortHotPlug == TRUE ) {
640       // RPR5.12 Hot Plug: PCIe Native Support
641       // RCINDP_Reg 0x10[3] = 0x1
642       // PCIe_Cfg 0x5A[8] = 0x1
643       // PCIe_Cfg 0x6C[6] = 0x1
644       // RCINDP_Reg 0x20[19] = 0x0
645       rwAlink ((SB_RCINDXP_REG10 | (UINT32) (RCINDXP << 29) | (portId << 24)), 0xFFFFFFFF, BIT3);
646       RWPCI (PCI_ADDRESS (0, GPP_DEV_NUM, portId, 0x5b), AccWidthUint8, 0xff, BIT0);
647       RWPCI (PCI_ADDRESS (0, GPP_DEV_NUM, portId, 0x6c), AccWidthUint8, 0xff, BIT6);
648       rwAlink ((SB_RCINDXP_REG20 | (UINT32) (RCINDXP << 29) | (portId << 24)), ~BIT19, 0);
649     }
650   }
651   if ( pConfig->GppUnhidePorts == FALSE ) {
652     if ((abValue & 0xF0) == 0) {
653       abValue = BIT8;         // if all ports are empty set GPP_RESET
654     } else if ((abValue & 0xE0) != 0 && (abValue & 0x10) == 0) {
655       abValue |= BIT4;        // PortA should always be visible whenever other ports are exist
656     }
657
658     // Update GPP_Portx_Enable (abcfg:0xC0[7:5])
659     writeAlink (SB_ABCFG_REGC0 | (UINT32) (ABCFG << 29), abValue);
660   }
661
662   //
663   // Common initialization for open GPP ports
664   //
665   for ( portId = 0; portId < MAX_GPP_PORTS; portId++ ) {
666     ReadPCI (PCI_ADDRESS (0, GPP_DEV_NUM, portId, 0x80), AccWidthUint8, &bValue);
667     if (bValue != 0xff) {
668       // Set pciCfg:PCIE_DEVICE_CNTL2[3:0] = 4'h6 (0x80[3:0])
669       bValue &= 0xf0;
670       bValue |= 0x06;
671       WritePCI (PCI_ADDRESS (0, GPP_DEV_NUM, portId, 0x80), AccWidthUint8, &bValue);
672
673         // Set PCIEIND_P:PCIE_RX_CNTL[RX_RCB_CPL_TIMEOUT_MODE] (0x70:[19]) = 1
674       abIndex = SB_RCINDXP_REG70 | (UINT32) (RCINDXP << 29) | (portId << 24);
675       abValue = readAlink (abIndex) | BIT19;
676       writeAlink (abIndex, abValue);
677
678         // Set PCIEIND_P:PCIE_TX_CNTL[TX_FLUSH_TLP_DIS] (0x20:[19]) = 0
679       abIndex = SB_RCINDXP_REG20 | (UINT32) (RCINDXP << 29) | (portId << 24);
680       abValue = readAlink (abIndex) & ~BIT19;
681       writeAlink (abIndex, abValue);
682
683         // Set Immediate Ack PM_Active_State_Request_L1 (0xA0:[23]) = 0
684       abIndex = SB_RCINDXP_REGA0 | (UINT32) (RCINDXP << 29) | (portId << 24);
685       abValue = readAlink (abIndex) & ~BIT23;
686       if ( pConfig->L1ImmediateAck == 0) {
687         abValue |= BIT23;
688       }
689       writeAlink (abIndex, abValue);
690     }
691   }
692 }
693
694
695 /**
696  * sbPcieGppLateInit - Late PCIE initialization for Hudson-2 GPP component
697  *
698  *
699  * @param[in] pConfig Southbridge configuration structure pointer.
700  *
701  */
702 VOID
703 sbPcieGppLateInit (
704   IN       AMDSBCFG* pConfig
705   )
706 {
707   UINT8            portId;
708   UINT8            busNum;
709   UINT8            aspmValue;
710   UINT8            PortaspmValue;
711   UINT8            reg8Value;
712   UINT8            cimGppPhyPllPowerDown;
713   SBGPPPORTCONFIG  *portCfg;
714   UINT32           reg32Value;
715
716   // Disable hidden register decode and serial number capability
717   reg32Value = readAlink (SB_ABCFG_REG330 | (UINT32) (ABCFG << 29));
718   writeAlink (SB_ABCFG_REG330 | (UINT32) (ABCFG << 29), reg32Value & ~(BIT26 + BIT10));
719
720   if (readAlink (SB_ABCFG_REGC0 | (UINT32) (ABCFG << 29)) & BIT8) {
721     return;
722   }
723
724   //
725   // Configure ASPM
726   //
727   //  writeAlink (0xC0 | (UINT32) (RCINDXC << 29), 0x400);  // Set STRAP_F0_MSI_EN
728   aspmValue = (UINT8)pConfig->GppPortAspm;
729   cimGppPhyPllPowerDown = (UINT8) pConfig->GppPhyPllPowerDown;
730 #if  SB_CIMx_PARAMETER == 0
731   aspmValue = cimGppPortAspmDefault;
732   cimGppPhyPllPowerDown = cimGppPhyPllPowerDownDefault;
733 #endif
734
735   reg8Value = 0x01;
736   for ( portId = 0; portId < MAX_GPP_PORTS; portId++ ) {
737     // write pci_reg3d with 0x01 to fix yellow mark for GPP bridge under Vista
738     // when native PCIE is enabled but MSI is not available
739     // SB02029: Hudson-2 BIF/GPP allowing strap STRAP_BIF_INTERRUPT_PIN_SB controlled by AB reg
740     portCfg = &pConfig->PORTCONFIG[portId].PortCfg;
741     if (portCfg->PortHotPlug) {
742       RWPCI (PCI_ADDRESS (0, 21, portId, 0x04), AccWidthUint8, 0xFE, 0x00);  //clear IO enable to fix possible hotplug hang
743     }
744     WritePCI (PCI_ADDRESS (0, 21, portId, 0x3d), AccWidthUint8, &reg8Value);
745     ReadPCI (PCI_ADDRESS (0, 21, portId, 0x19), AccWidthUint8, &busNum);
746     if (busNum != 0xFF) {
747       ReadPCI (PCI_ADDRESS (busNum, 0, 0, 0x00), AccWidthUint32, &reg32Value);
748       if (reg32Value != 0xffffffff) {
749         PortaspmValue = aspmValue;
750         // Vlidate if EP support ASPM
751         sbGppValidateAspm (PCI_ADDRESS (busNum, 0, 0, 0), &PortaspmValue);
752         // Set ASPM on EP side
753         sbGppSetEPAspm (PCI_ADDRESS (busNum, 0, 0, 0), PortaspmValue);
754         // Set ASPM on port side
755         sbGppSetAspm (PCI_ADDRESS (0, 21, portId, 0), PortaspmValue);
756       }
757     }
758     rwAlink ((SB_RCINDXP_REG02 | (UINT32) (RCINDXP << 29) | (portId << 24) ), ~(BIT15), (BIT15));
759   }
760   rwAlink ((SB_RCINDXC_REG02 | (UINT32) (RCINDXC << 29)), ~(BIT0), (BIT0));
761
762   //
763   // Configure Lock HWInit registers
764   //
765   reg32Value = readAlink (SB_ABCFG_REGC0 | (UINT32) (ABCFG << 29));
766   if (reg32Value & 0xF0) {
767     reg32Value = readAlink (SB_RCINDXC_REG10 | (UINT32) (RCINDXC << 29));
768     writeAlink (SB_RCINDXC_REG10 | (UINT32) (RCINDXC << 29), reg32Value | BIT0);  // Set HWINIT_WR_LOCK
769
770     if ( cimGppPhyPllPowerDown == TRUE ) {
771       //
772       // RPR 5.4 Power Saving Feature for GPP Lanes
773       //
774       UINT32  abValue;
775
776       // Set PCIE_P_CNTL in Alink PCIEIND space
777       abValue = readAlink (RC_INDXC_REG40 | (UINT32) (RCINDXC << 29));
778       abValue |= BIT12 + BIT3 + BIT0;
779       abValue &= ~(BIT9 + BIT4);
780       writeAlink (RC_INDXC_REG40 | (UINT32) (RCINDXC << 29), abValue);
781       rwAlink (SB_RCINDXC_REG02, ~(BIT8), (BIT8));
782       rwAlink (SB_RCINDXC_REG02, ~(BIT3), (BIT3));
783     }
784   }
785
786   // Restore strap0 via override
787   if (pConfig->PcieAER) {
788     rwAlink (SB_ABCFG_REG310 | (UINT32) (ABCFG << 29), 0xFFFFFFFF, BIT7);
789     rwAlink (RC_INDXC_REGC0, 0xFFFFFFFF, BIT9);
790   }
791 }
792
793
794 /**
795  * sbGppDynamicPowerSaving - RPR 5.19 GPP Dynamic Power Saving
796  *
797  *
798  * @param[in] pConfig
799  *
800  */
801 VOID
802 sbGppDynamicPowerSaving (
803   IN       AMDSBCFG* pConfig
804   )
805 {
806   SBGPPPORTCONFIG  *portCfg;
807   UINT8            cimGppLaneReversal;
808   UINT8            cimAlinkPhyPllPowerDown;
809   UINT8            cimGppPhyPllPowerDown;
810   UINT32           Data32;
811   UINT32           HoldData32;
812   UINT32           abValue;
813
814   if (!pConfig->GppDynamicPowerSaving || pConfig->sdbEnable) {
815     return;
816   }
817
818   cimAlinkPhyPllPowerDown = (UINT8) pConfig->AlinkPhyPllPowerDown;
819   cimGppLaneReversal =  (UINT8) pConfig->GppLaneReversal;
820   cimGppPhyPllPowerDown =  (UINT8) pConfig->GppPhyPllPowerDown;
821 #if  SB_CIMx_PARAMETER == 0
822   cimGppLaneReversal = cimGppLaneReversalDefault;
823   cimAlinkPhyPllPowerDown = cimAlinkPhyPllPowerDownDefault;
824   cimGppPhyPllPowerDown = cimGppPhyPllPowerDownDefault;
825 #endif
826   if (pConfig->GppHardwareDowngrade) {
827     portCfg = &pConfig->PORTCONFIG[pConfig->GppHardwareDowngrade - 1].PortCfg;
828     portCfg->PortDetected = TRUE;
829   }
830
831   Data32 = 0;
832   HoldData32 = 0;
833   switch ( pConfig->GppLinkConfig ) {
834   case GPP_CFGMODE_X4000:
835     portCfg = &pConfig->PORTCONFIG[0].PortCfg;
836     if ( portCfg->PortDetected == FALSE ) {
837       Data32 |= 0x0f0f;
838       HoldData32 |= 0x1000;
839     }
840     break;
841   case GPP_CFGMODE_X2200:
842     portCfg = &pConfig->PORTCONFIG[0].PortCfg;
843     if ( portCfg->PortDetected == FALSE ) {
844       Data32 |= ( cimGppLaneReversal )? 0x0c0c:0x0303;
845       HoldData32 |= 0x1000;
846     }
847     portCfg = &pConfig->PORTCONFIG[1].PortCfg;
848     if ( portCfg->PortDetected == FALSE ) {
849       Data32 |= ( cimGppLaneReversal )? 0x0303:0x0c0c;
850       HoldData32 |= 0x2000;
851     }
852     break;
853   case GPP_CFGMODE_X2110:
854     portCfg = &pConfig->PORTCONFIG[0].PortCfg;
855     if ( portCfg->PortDetected == FALSE ) {
856       Data32 |= ( cimGppLaneReversal )? 0x0c0c:0x0303;
857       HoldData32 |= 0x1000;
858     }
859     portCfg = &pConfig->PORTCONFIG[1].PortCfg;
860     if ( portCfg->PortDetected == FALSE ) {
861       Data32 |= ( cimGppLaneReversal )? 0x0202:0x0404;
862       HoldData32 |= 0x2000;
863     }
864     portCfg = &pConfig->PORTCONFIG[2].PortCfg;
865     if ( portCfg->PortDetected == FALSE ) {
866       Data32 |= ( cimGppLaneReversal )? 0x0101:0x0808;
867       HoldData32 |= 0x4000;
868     }
869     break;
870   case GPP_CFGMODE_X1111:
871     portCfg = &pConfig->PORTCONFIG[0].PortCfg;
872     if ( portCfg->PortDetected == FALSE ) {
873       Data32 |= ( cimGppLaneReversal )? 0x0808:0x0101;
874       HoldData32 |= 0x1000;
875     }
876     portCfg = &pConfig->PORTCONFIG[1].PortCfg;
877     if ( portCfg->PortDetected == FALSE ) {
878       Data32 |= ( cimGppLaneReversal )? 0x0404:0x0202;
879       HoldData32 |= 0x2000;
880     }
881     portCfg = &pConfig->PORTCONFIG[2].PortCfg;
882     if ( portCfg->PortDetected == FALSE ) {
883       Data32 |= ( cimGppLaneReversal )? 0x0202:0x0404;
884       HoldData32 |= 0x4000;
885     }
886     portCfg = &pConfig->PORTCONFIG[3].PortCfg;
887     if ( portCfg->PortDetected == FALSE ) {
888       Data32 |= ( cimGppLaneReversal )? 0x0101:0x0808;
889       HoldData32 |= 0x8000;
890     }
891     break;
892   default:
893     break;
894   }
895
896   // RPR 5.11 Power Saving With GPP Disable
897   // ABCFG 0xC0[8] = 0x0
898   // ABCFG 0xC0[15:12] = 0xF
899   // Enable "Power Saving Feature for A-Link Express Lanes"
900   // Enable "Power Saving Feature for GPP Lanes"
901   // ABCFG 0x90[19] = 1
902   // ABCFG 0x90[6] = 1
903   // RCINDC_Reg 0x65 [27:0] = 0xFFFFFFF
904   // ABCFG 0xC0[7:4] = 0x0
905   if ( cimAlinkPhyPllPowerDown && cimGppPhyPllPowerDown ) {
906     abValue = readAlink (SB_ABCFG_REGC0 | (UINT32) (ABCFG << 29));
907     writeAlink (SB_ABCFG_REGC0 | (UINT32) (ABCFG << 29), (( abValue | HoldData32 ) & (~ BIT8 )));
908     rwAlink (SB_AX_INDXC_REG40, ~(BIT9 + BIT4), (BIT0 + BIT3 + BIT12));
909     rwAlink ((SB_ABCFG_REG90 | (UINT32) (ABCFG << 29)), 0xFFFFFFFF, (BIT6 + BIT19));
910     rwAlink (RC_INDXC_REG65, 0xFFFFFFFF, ((Data32 & 0x0F) == 0x0F) ? Data32 | 0x0CFF0000 : Data32);
911     rwAlink (RC_INDXC_REG40, ~(BIT9 + BIT4), (BIT0 + BIT3 + BIT12));
912   }
913 }
914
915
916 /**
917  * sbGppAerInitialization - Initializing AER
918  *
919  *
920  * @param[in] pConfig
921  *
922  */
923 VOID
924 sbGppAerInitialization (
925   IN       AMDSBCFG* pConfig
926   )
927 {
928   UINT8    PortId;
929   UINT32   ValueDd;
930
931   if (pConfig->PcieAER) {
932     // GPP strap configuration
933     rwAlink (SB_ABCFG_REG310 | (UINT32) (ABCFG << 29), ~(BIT7 + BIT4), BIT28 + BIT27 + BIT26 + BIT1);
934     rwAlink (SB_ABCFG_REG314 | (UINT32) (ABCFG << 29), ~(UINT32) (0xfff << 15), 0);
935
936     for (PortId = 0; PortId < MAX_GPP_PORTS; PortId++) {
937       ReadPCI (PCI_ADDRESS (0, GPP_DEV_NUM, PortId, 0x00), AccWidthUint32, &ValueDd);
938       if (ValueDd != 0xffffffff) {
939         rwAlink ((SB_RCINDXP_REG6A | (UINT32) (RCINDXP << 29) | (PortId << 24)), ~BIT1, 0);
940         rwAlink ((SB_RCINDXP_REG70 | (UINT32) (RCINDXP << 29) | (PortId << 24)), 0xFFFFE000, 0);
941       }
942     }
943
944     rwAlink (SB_RCINDXC_REG10, ~(BIT18 + BIT21 + BIT22), 0);
945
946     // AB strap configuration
947     rwAlink (SB_ABCFG_REGF0 | (UINT32) (ABCFG << 29), 0xFFFFFFFF, BIT15 + BIT14);
948     rwAlink (SB_ABCFG_REGF4 | (UINT32) (ABCFG << 29), 0xFFFFFFFF, BIT3);
949
950     // Enable GPP function0 error reporting
951     rwAlink (SB_ABCFG_REG310 | (UINT32) (ABCFG << 29), ~BIT7, BIT7);
952     rwAlink (SB_RCINDXC_REGC0, ~BIT9, BIT9);
953   } else {
954     //OBS220313: Hard System Hang running MeatGrinder Test on multiple blocks
955     //RPR 5.13 GPP Error Reporting Configuration
956     rwAlink (SB_ABCFG_REGF0 | (UINT32) (ABCFG << 29), ~(BIT1), 0);
957     //rwAlink (SB_ABCFG_REG310 | (UINT32) (ABCFG << 29), ~BIT7, 0);
958     //rwAlink (SB_RCINDXC_REGC0, ~BIT8, 0);
959   }
960   //RPR 5.13 GPP Error Reporting Configuration
961   rwAlink (SB_ABCFG_REGB8 | (UINT32) (ABCFG << 29), ~(BIT8 + BIT24 + BIT25 + BIT26 + BIT28), BIT8 + BIT24 + BIT26 + BIT28);
962 }
963
964 /**
965  * sbGppRasInitialization - Initializing RAS
966  *
967  *
968  * @param[in] pConfig
969  *
970  */
971 VOID
972 sbGppRasInitialization (
973   IN     AMDSBCFG*   pConfig
974   )
975 {
976   if (pConfig->PcieRAS) {
977     rwAlink (SB_ABCFG_REGF4 | (UINT32) (ABCFG << 29), 0xFFFFFFFF, BIT0);
978   }
979 }
980
981
982 //
983 //-----------------------------------------------------------------------------------
984 // Early Hudson-2 GPP initialization sequence:
985 //
986 // 1) Set port enable bit fields by current GPP link configuration mode
987 // 2) Deassert GPP reset and pull EP out of reset - Clear GPP_RESET (abcfg:0xC0[8] = 0)
988 // 3) Loop polling for the link status of all ports
989 // 4) Misc operations after link training:
990 //      - (optional) Detect GFX device
991 //      - Hide empty GPP configuration spaces (Disable empty GPP ports)
992 //      - (optional) Power down unused GPP ports
993 //      - (optional) Configure PCIE_P2P_Int_Map (abcfg:0xC4[7:0])
994 // 5) GPP init completed
995 //
996 //
997 // *) Gen2 vs Gen1
998 //                                   Gen2 mode     Gen1 mode
999 //  ---------------------------------------------------------------
1000 //    STRAP_PHY_PLL_CLKF[6:0]          7'h32         7'h19
1001 //    STRAP_BIF_GEN2_EN                  1             0
1002 //
1003 //    PCIE_PHY_PLL clock locks @       5GHz
1004 //
1005 //
1006
1007 /**
1008  * GPP early programming and link training. On exit all populated EPs should be fully operational.
1009  *
1010  *
1011  *
1012  * @param[in] pConfig Southbridge configuration structure pointer.
1013  *
1014  */
1015 VOID
1016 sbPcieGppEarlyInit (
1017   IN       AMDSBCFG* pConfig
1018   )
1019 {
1020   UINT32           reg32Value;
1021   UINT8            cimNbSbGen2;
1022   UINT8            cimGppMemWrImprove;
1023   UINT8            cimGppLaneReversal;
1024   UINT8            cimAlinkPhyPllPowerDown;
1025   UINT32           abValue;
1026
1027   cimNbSbGen2 = pConfig->NbSbGen2;
1028   cimGppMemWrImprove = pConfig->GppMemWrImprove;
1029   cimGppLaneReversal = (UINT8) pConfig->GppLaneReversal;
1030   cimAlinkPhyPllPowerDown = (UINT8) pConfig->AlinkPhyPllPowerDown;
1031 #if  SB_CIMx_PARAMETER == 0
1032   cimNbSbGen2 = cimNbSbGen2Default;
1033   cimGppMemWrImprove = cimGppMemWrImproveDefault;
1034   cimGppLaneReversal = cimGppLaneReversalDefault;
1035   cimAlinkPhyPllPowerDown = cimAlinkPhyPllPowerDownDefault;
1036 #endif
1037
1038   outPort80 (0x90);
1039   //
1040   // Configure NB-SB link PCIE PHY PLL power down for L1
1041   //
1042   if ( cimAlinkPhyPllPowerDown == TRUE ) {
1043     // Set PCIE_P_CNTL in Alink PCIEIND space
1044     writeAlink (SB_AX_INDXC_REG30 | (UINT32) (AXINDC << 29), 0x40);
1045     abValue = readAlink (SB_AX_DATAC_REG34 | (UINT32) (AXINDC << 29));
1046     abValue |= BIT12 + BIT3 + BIT0;
1047     abValue &= ~(BIT9 + BIT4);
1048     writeAlink (SB_AX_DATAC_REG34 | (UINT32) (AXINDC << 29), abValue);
1049     rwAlink (SB_AX_INDXC_REG02 | (UINT32) (AXINDC << 29), ~(BIT8), (BIT8));
1050     rwAlink (SB_AX_INDXC_REG02 | (UINT32) (AXINDC << 29), ~(BIT3), (BIT3));
1051   }
1052
1053   // AXINDC_Reg 0xA4[18] = 0x1
1054   writeAlink (SB_AX_INDXP_REG38 | (UINT32) (AXINDP << 29), 0xA4);
1055   abValue = readAlink (SB_AX_DATAP_REG3C | (UINT32) (AXINDP << 29));
1056   abValue |= BIT18;
1057   writeAlink (SB_AX_DATAP_REG3C | (UINT32) (AXINDP << 29), abValue);
1058
1059
1060   //
1061   // Set ABCFG 0x031C[0] = 1 to enable lane reversal
1062   //
1063   reg32Value = readAlink (SB_ABCFG_REG31C | (UINT32) (ABCFG << 29));
1064   if ( cimGppLaneReversal ) {
1065     writeAlink (SB_ABCFG_REG31C | (UINT32) (ABCFG << 29), reg32Value | BIT0);
1066   } else {
1067     writeAlink (SB_ABCFG_REG31C | (UINT32) (ABCFG << 29), reg32Value | 0x00);
1068   }
1069   //
1070   // Set abcfg:0x90[20] = 1 to enable GPP bridge multi-function
1071   //
1072   reg32Value = readAlink (SB_ABCFG_REG90 | (UINT32) (ABCFG << 29));
1073   writeAlink (SB_ABCFG_REG90 | (UINT32) (ABCFG << 29), reg32Value | BIT20);
1074
1075
1076   //
1077   // Initialize and configure GPP
1078   //
1079   if (pConfig->GppFunctionEnable) {
1080     sbGppTogglePcieReset (pConfig);
1081
1082     // PreInit - Enable GPP link training
1083     PreInitGppLink (pConfig);
1084
1085     //
1086     // GPP Upstream Memory Write Arbitration Enhancement ABCFG 0x54[26] = 1
1087     // GPP Memory Write Max Payload Improvement RCINDC_Reg 0x10[12:10] = 0x4
1088     //
1089     if ( cimGppMemWrImprove == TRUE ) {
1090       rwAlink (SB_ABCFG_REG54 | (UINT32) (ABCFG << 29), ~BIT26, (BIT26));
1091       rwAlink (SB_RCINDXC_REG10 | (UINT32) (RCINDXC << 29), ~(BIT12 + BIT11 + BIT10), (BIT12));
1092     }
1093
1094     if (CheckGppLinkStatus (pConfig) && !pConfig->S3Resume) {
1095       // Toggle GPP reset (Note this affects all Hudson-2 GPP ports)
1096       sbGppTogglePcieReset (pConfig);
1097     }
1098
1099     // Misc operations after link training
1100     AfterGppLinkInit (pConfig);
1101
1102
1103     sbGppAerInitialization (pConfig);
1104     sbGppRasInitialization (pConfig);
1105   }
1106   sbGppDynamicPowerSaving (pConfig);
1107   outPort80 (0x9F);
1108 }
1109