blob: 9ea0a53e408094fb1947ae2dbef4d4522f45f413 [file] [log] [blame]
zbao7d94cf92012-07-02 14:19:14 +08001/* $NoKeywords:$ */
2/**
3 * @file
4 *
5 * Fch Gpp Library
6 *
7 * Gpp Library
8 *
9 * @xrefitem bom "File Content Label" "Release Content"
10 * @e project: AGESA
11 * @e sub-project: FCH
12 * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
13 *
14 */
15/*
16*****************************************************************************
17*
Siyuan Wang641f00c2013-06-08 11:50:55 +080018 * Copyright (c) 2008 - 2012, 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.
zbao7d94cf92012-07-02 14:19:14 +080042****************************************************************************
43*/
44#include "FchPlatform.h"
45#include "Filecode.h"
46#include "FchDef.h"
47#define FILECODE PROC_FCH_PCIE_GPPLIB_FILECODE
48
49/**
50 * FchGppForceGen2 - Set GPP to Gen2
51 *
52 *
53 * @param[in] FchGpp Pointer to Fch GPP configuration structure
54 * @param[in] ActivePorts Activate Ports
55 * @param[in] StdHeader Pointer to AMD_CONFIG_PARAMS
56 *
57 */
58VOID
59FchGppForceGen2 (
60 IN FCH_GPP *FchGpp,
61 IN CONST UINT8 ActivePorts,
62 IN AMD_CONFIG_PARAMS *StdHeader
63 )
64{
65 UINT32 PortId;
66
67 for ( PortId = 0; PortId < MAX_GPP_PORTS; PortId++ ) {
68 if (ActivePorts & (1 << PortId)) {
69 RwAlink (FCH_RCINDXP_REGA4 | PortId << 24, 0xFFFFFFFF, BIT29 + BIT0, StdHeader);
70 RwAlink ((FCH_ABCFG_REG340 + PortId * 4) | (UINT32) (ABCFG << 29), 0xFFFFFFFF, BIT21, StdHeader);
71 RwAlink (FCH_RCINDXP_REGA2 | PortId << 24, (UINT32)~BIT13, 0, StdHeader);
72 RwAlink (FCH_RCINDXP_REGC0 | PortId << 24, (UINT32)~BIT15, 0, StdHeader);
73 RwPci (PCI_ADDRESS (0, GPP_DEV_NUM, PortId, 0x88), AccessWidth8, 0xf0, 0x02, StdHeader);
74
75 (&FchGpp->PortCfg[PortId])->PortIsGen2 = TRUE;
76 }
77 }
78}
79
80/**
81 * FchGppForceGen1 - Set GPP to Gen1
82 *
83 *
84 * @param[in] FchGpp Pointer to Fch GPP configuration structure
85 * @param[in] ActivePorts Activate Ports
86 * @param[in] StdHeader Pointer to AMD_CONFIG_PARAMS
87 *
88 */
89VOID
90FchGppForceGen1 (
91 IN FCH_GPP *FchGpp,
92 IN CONST UINT8 ActivePorts,
93 IN AMD_CONFIG_PARAMS *StdHeader
94 )
95{
96 UINT32 PortId;
97
98 for ( PortId = 0; PortId < MAX_GPP_PORTS; PortId++ ) {
99 if (ActivePorts & (1 << PortId) && FchGpp->GppHardwareDownGrade != PortId + 1) {
100 RwAlink ((FCH_ABCFG_REG340 + PortId * 4) | (UINT32) (ABCFG << 29), (UINT32)~BIT21, 0, StdHeader);
101 RwAlink (FCH_RCINDXP_REGA4 | PortId << 24, (UINT32)~BIT0, BIT29, StdHeader);
102 RwAlink (FCH_RCINDXP_REGA2 | PortId << 24, 0xFFFFFFFF, BIT13, StdHeader);
103 RwAlink (FCH_RCINDXP_REGC0 | PortId << 24, (UINT32)~BIT15, 0, StdHeader);
104 RwPci (PCI_ADDRESS (0, GPP_DEV_NUM, PortId, 0x88), AccessWidth8, 0xf0, 0x01, StdHeader);
105
106 (&FchGpp->PortCfg[PortId])->PortIsGen2 = FALSE;
107 }
108 }
109}
110
111/**
112 * GppPortPollingLtssm - Loop polling the LTSSM for each GPP port marked in PortMap
113 *
114 *
115 * @param[in] FchGpp Pointer to Fch GPP configuration structure
116 * @param[in] ActivePorts A bitmap of ports which should be polled
117 * @param[in] IsGen2 TRUE if the polling is in Gen2 mode
118 * @param[in] StdHeader Pointer to AMD_CONFIG_PARAMS
119 *
120 * @retval FailedPorts A bitmap of ports which failed to train
121 *
122 */
123UINT8
124GppPortPollingLtssm (
125 IN FCH_GPP *FchGpp,
126 IN UINT8 ActivePorts,
127 IN BOOLEAN IsGen2,
128 IN AMD_CONFIG_PARAMS *StdHeader
129 )
130{
131 UINT32 RetryCounter;
132 UINT8 PortId;
133 UINT8 FailedPorts;
134 UINT8 HotPlugPorts;
135 FCH_GPP_PORT_CONFIG *PortCfg;
136 UINT32 AbIndex;
137 UINT32 GppData32;
138 UINT8 EmptyPorts;
139 UINT8 Index;
140 UINT8 FixedPolling;
141
142 FailedPorts = 0;
143 HotPlugPorts = 0;
144 RetryCounter = MAX_LT_POLLINGS;
145 EmptyPorts = ActivePorts;
146 FixedPolling = 200;
147 if ( FchGpp->NewGppAlgorithm == TRUE ) {
148 FixedPolling = FchGpp->GppPortMinPollingTime;
149 }
150 while (RetryCounter-- && ActivePorts) {
151 for (PortId = 0; PortId < MAX_GPP_PORTS; PortId++) {
152 if (ActivePorts & (1 << PortId)) {
153 PortCfg = &FchGpp->PortCfg[PortId];
154 if ( PortCfg->PortHotPlug == TRUE ) {
155 HotPlugPorts |= ( 1 << PortId);
156 }
157 AbIndex = FCH_RCINDXP_REGA5 | (UINT32) (PortId << 24);
158 GppData32 = ReadAlink (AbIndex, StdHeader) & 0x3F3F3F3F;
159
160 if ((UINT8) (GppData32) > 0x04) {
161 EmptyPorts &= ~(1 << PortId);
162 }
163
164 if ((UINT8) (GppData32) == 0x10) {
165 ActivePorts &= ~(1 << PortId);
166 PortCfg->PortDetected = TRUE;
167 break;
168 }
169
170 if (IsGen2) {
171 for (Index = 0; Index < 4; Index++) {
172 if ((UINT8) (GppData32) == 0x29 || (UINT8) (GppData32) == 0x2A ) {
173 ActivePorts &= ~(1 << PortId);
174 FailedPorts |= (1 << PortId);
175 break;
176 }
177 GppData32 >>= 8;
178 }
179 }
180 }
181 }
182 if (EmptyPorts && RetryCounter < (MAX_LT_POLLINGS - (UINT32) FixedPolling)) {
183 ActivePorts &= ~EmptyPorts;
184 }
185 FchStall (1000, StdHeader);
186 }
187 FchGpp->HotPlugPortsStatus = HotPlugPorts;
188
189 FailedPorts |= ActivePorts;
190 return FailedPorts;
191}
192
193
194/**
195 * FchFindPciCap - Find PCI Cap
196 *
197 *
198 * @param[in] PciAddress PCI Address.
199 * @param[in] TargetCapId Target Cap ID.
200 * @param[in] StdHeader
201 *
202 */
203UINT8
204FchFindPciCap (
205 IN UINT32 PciAddress,
206 IN UINT8 TargetCapId,
207 IN AMD_CONFIG_PARAMS *StdHeader
208 )
209{
210 UINT8 NextCapPtr;
211 UINT8 CapId;
212
213 NextCapPtr = 0x34;
214 while (NextCapPtr != 0) {
215 ReadPci (PciAddress + NextCapPtr, AccessWidth8, &NextCapPtr, StdHeader);
216
217 if (NextCapPtr == 0xff) {
218 return 0;
219 }
220
221 if (NextCapPtr != 0) {
222 ReadPci (PciAddress + NextCapPtr, AccessWidth8, &CapId, StdHeader);
223 if (CapId == TargetCapId) {
224 break;
225 } else {
226 NextCapPtr++;
227 }
228 }
229 }
230 return NextCapPtr;
231}
232
233STATIC
234BOOLEAN
235IsDeviceGen2Capable (
236 IN UINT32 pciAddress,
237 IN AMD_CONFIG_PARAMS *StdHeader
238 )
239{
240 UINT8 pcieCapOffset;
241 UINT8 value8;
242 UINT16 value16;
243
244 pcieCapOffset = FchFindPciCap (pciAddress, PCIE_CAP_ID, StdHeader);
245 if (pcieCapOffset) {
246 ReadPci (pciAddress + pcieCapOffset + 0x0C, AccessWidth8, &value8, StdHeader);
247 if (value8 & BIT1) {
248 return TRUE;
249 } else {
250 ReadPci (pciAddress, AccessWidth16, &value16, StdHeader);
251 if ((value16 == AMD_FCH_VID) || (value16 == ATI_VID)) {
252 return TRUE;
253 }
254 }
255 }
256 return FALSE;
257}
258
259
260/**
261 *
262 * 5/10/2011 - BIOS workaround for PLLPD hangup issue (applied for both POST and hotplug phases):
263 *
264 * if (GppPhyPllPowerDown == TRUE) {
265 * if (GppGen2 == TRUE && GppGen2Strap == TRUE) {
266 * if ((Any EP is GEN2 capable) || (Any EP is AMD/ATI GFX card)) {
267 * INDXC_REG40[3] = 0;
268 * } else {
269 * INDXC_REG40[3] = 1;
270 * }
271 * } else {
272 * INDXC_REG40[3] = 1;
273 * }
274 * }
275 *
276 *
277 *
278 * @param[in] FchGpp Pointer to Fch GPP configuration structure
279 * @param[in] StdHeader Pointer to AMD_CONFIG_PARAMS
280 *
281 */
282VOID
283GppGen2Workaround (
284 IN FCH_GPP *FchGpp,
285 IN AMD_CONFIG_PARAMS *StdHeader
286 )
287{
288 UINT8 portId;
289 UINT8 busNum;
290 UINT32 reg32Value;
291 BOOLEAN DisablePllPdInL1;
292
293 if (FchGpp->GppPhyPllPowerDown == TRUE) {
294 DisablePllPdInL1 = FALSE;
295 if (FchGpp->GppGen2 && FchGpp->GppGen2Strap) {
296 // Search all EP for max link speed capability
297 for ( portId = 0; portId < MAX_GPP_PORTS; portId++ ) {
298 ReadPci (PCI_ADDRESS (0, FCH_GPP_DEV, portId, 0x19), AccessWidth8, &busNum, StdHeader);
299 if (busNum != 0xFF) {
300 ReadPci (PCI_ADDRESS (busNum, 0, 0, 0x00), AccessWidth32, &reg32Value, StdHeader);
301 if (reg32Value != 0xffffffff) {
302 DisablePllPdInL1 = IsDeviceGen2Capable (PCI_ADDRESS (busNum, 0, 0, 0), StdHeader);
303 if (DisablePllPdInL1 == TRUE) {
304 break;
305 }
306 }
307 }
308 }
309 }
310
311 if (DisablePllPdInL1 == TRUE) {
312 RwAlink (FCH_RCINDXC_REG40, (UINT32)~BIT3, 0, StdHeader);
313 } else {
314 RwAlink (FCH_RCINDXC_REG40, (UINT32)~BIT3, BIT3, StdHeader);
315 }
316 }
317}
318
319UINT32
320GppGetFchTempBus (
321 IN AMD_CONFIG_PARAMS *StdHeader
322 )
323{
324 UINT32 FchTempBus;
325 UINT8 TempValue;
326 UINT64 MmioMsr;
327
328 LibAmdMsrRead (0xC0010058, &MmioMsr, StdHeader);
329 TempValue = (UINT8) ((MmioMsr & 0x03C) >> 2);
330 FchTempBus = ( 0x01 << TempValue);
331 FchTempBus--;
332 FchTempBus--;
333 return ( FchTempBus);
334}