blob: 02329912c738bf68b2ddd402ddd1d20365769d72 [file] [log] [blame]
zbao7d94cf92012-07-02 14:19:14 +08001/* $NoKeywords:$ */
2/**
3 * @file
4 *
5 * Various workarounds
6 *
7 *
8 *
9 * @xrefitem bom "File Content Label" "Release Content"
10 * @e project: AGESA
11 * @e sub-project: GNB
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*/
45
46/*----------------------------------------------------------------------------------------
47 * M O D U L E S U S E D
48 *----------------------------------------------------------------------------------------
49 */
50#include "AGESA.h"
51#include "Ids.h"
52#include "amdlib.h"
53#include "Gnb.h"
54#include "GnbPcie.h"
55#include "GnbCommonLib.h"
56#include "GnbPcieConfig.h"
57#include "GnbRegistersLN.h"
58#include "PcieWorkarounds.h"
59#include "Filecode.h"
60#define FILECODE PROC_GNB_MODULES_GNBPCIETRAININGV1_PCIEWORKAROUNDS_FILECODE
61/*----------------------------------------------------------------------------------------
62 * D E F I N I T I O N S A N D M A C R O S
63 *----------------------------------------------------------------------------------------
64 */
65
66extern BUILD_OPT_CFG UserOptions;
67
68/*----------------------------------------------------------------------------------------
69 * T Y P E D E F S A N D S T R U C T U R E S
70 *----------------------------------------------------------------------------------------
71 */
72AGESA_STATUS
73PcieConfigureBridgeResources (
74 IN PCI_ADDR Port,
75 IN AMD_CONFIG_PARAMS *StdHeader
76 );
77
78VOID
79PcieFreeBridgeResources (
80 IN PCI_ADDR Port,
81 IN AMD_CONFIG_PARAMS *StdHeader
82 );
83
84GFX_WORKAROUND_STATUS
85PcieDeskewWorkaround (
86 IN PCI_ADDR Device,
87 IN AMD_CONFIG_PARAMS *StdHeader
88 );
89
90GFX_WORKAROUND_STATUS
91PcieNvWorkaround (
92 IN PCI_ADDR Device,
93 IN AMD_CONFIG_PARAMS *StdHeader
94 );
95
96VOID
97PcieProgramCpuMmio (
98 OUT UINT32 *SaveValues,
99 IN AMD_CONFIG_PARAMS *StdHeader
100 );
101
102VOID
103PcieRestoreCpuMmio (
104 IN UINT32 *RestoreValues,
105 IN AMD_CONFIG_PARAMS *StdHeader
106 );
107
108BOOLEAN
109PcieIsDeskewCardDetected (
110 IN UINT16 DeviceId
111 );
112
113/*----------------------------------------------------------------------------------------
114 * P R O T O T Y P E S O F L O C A L F U N C T I O N S
115 *----------------------------------------------------------------------------------------
116 */
117
118/*----------------------------------------------------------------------------------------*/
119/**
120 * ATI RV370/RV380 card workaround
121 *
122 *
123 *
124 * @param[in] Port PCI addreses of the port
125 * @param[in] StdHeader Standard configuration header
126 * @retval GFX_WORKAROUND_STATUS Return the GFX Card Workaround status
127 */
128GFX_WORKAROUND_STATUS
129PcieGfxCardWorkaround (
130 IN PCI_ADDR Port,
131 IN AMD_CONFIG_PARAMS *StdHeader
132 )
133{
134 GFX_WORKAROUND_STATUS Status;
135 UINT16 DeviceId;
136 UINT16 VendorId;
137 UINT8 DevClassCode;
138 UINT32 SaveValueData[2];
139 PCI_ADDR Ep;
140
141 Status = GFX_WORKAROUND_SUCCESS;
142
143 Ep.AddressValue = MAKE_SBDFO (0, Port.Address.Bus + Port.Address.Device, 0, 0, 0);
144 if (PcieConfigureBridgeResources (Port, StdHeader) == AGESA_SUCCESS) {
145 GnbLibPciRead (Ep.AddressValue | 0x00, AccessWidth16, &DeviceId, StdHeader);
146 Status = GFX_WORKAROUND_DEVICE_NOT_READY;
147 if (DeviceId != 0xffff) {
148 GnbLibPciRead (Ep.AddressValue | 0x02, AccessWidth16, &VendorId, StdHeader);
149 if (VendorId != 0xffff) {
150 GnbLibPciRead (Ep.AddressValue | 0x0B, AccessWidth8, &DevClassCode, StdHeader);
151 Status = GFX_WORKAROUND_SUCCESS;
152 if (DevClassCode == 3) {
153 PcieProgramCpuMmio (SaveValueData, StdHeader);
154 if (VendorId == 0x1002 && PcieIsDeskewCardDetected (DeviceId)) {
155 Status = PcieDeskewWorkaround (Ep, StdHeader);
156 } else if (VendorId == 0x10DE) {
157 Status = PcieNvWorkaround (Ep, StdHeader);
158 }
159 PcieRestoreCpuMmio (SaveValueData, StdHeader);
160 }
161 }
162 }
163 PcieFreeBridgeResources (Port, StdHeader);
164 }
165 return Status;
166}
167
168
169/*----------------------------------------------------------------------------------------*/
170/**
171 * RV370/RV380 Deskew workaround
172 *
173 *
174 *
175 * @param[in] Device Pcie Address of ATI RV370/RV380 card.
176 * @param[in] StdHeader Standard configuration header
177 */
178GFX_WORKAROUND_STATUS
179PcieDeskewWorkaround (
180 IN PCI_ADDR Device,
181 IN AMD_CONFIG_PARAMS *StdHeader
182 )
183{
184 UINTN MmioBase;
185 UINT16 MmioData1;
186 UINT32 MmioData2;
187
188 MmioBase = UserOptions.CfgTempPcieMmioBaseAddress;
189 if (MmioBase == 0) {
190 return GFX_WORKAROUND_SUCCESS;
191 }
192 GnbLibPciWrite (Device.AddressValue | 0x18, AccessWidth32, &MmioBase, StdHeader);
193 GnbLibPciRMW (Device.AddressValue | 0x04, AccessWidth8 , (UINT32)~BIT1, (UINT32)BIT1, StdHeader);
194 GnbLibMemRMW (MmioBase + 0x120, AccessWidth16, 0, 0xb700, StdHeader);
195 GnbLibMemRead (MmioBase + 0x120, AccessWidth16, &MmioData1, StdHeader);
196 if (MmioData1 == 0xb700) {
197 GnbLibMemRMW (MmioBase + 0x124, AccessWidth32, 0, 0x13, StdHeader);
198 GnbLibMemRead (MmioBase + 0x124, AccessWidth32, &MmioData2, StdHeader);
199 if (MmioData2 == 0x13) {
200 GnbLibMemRead (MmioBase + 0x12C, AccessWidth32, &MmioData2, StdHeader);
201 if (MmioData2 & BIT8) {
202 return GFX_WORKAROUND_RESET_DEVICE;
203 }
204 }
205 }
206 GnbLibPciRMW (Device.AddressValue | 0x04, AccessWidth8, (UINT32)~BIT1, 0x0, StdHeader);
207 GnbLibPciRMW (Device.AddressValue | 0x18, AccessWidth32, 0x0, 0x0, StdHeader);
208
209 return GFX_WORKAROUND_SUCCESS;
210}
211
212/*----------------------------------------------------------------------------------------*/
213/**
214 * NV43 card workaround (lost SSID)
215 *
216 *
217 *
218 * @param[in] Device Pcie Address of NV43 card.
219 * @param[in] StdHeader Standard configuration header
220 */
221GFX_WORKAROUND_STATUS
222PcieNvWorkaround (
223 IN PCI_ADDR Device,
224 IN AMD_CONFIG_PARAMS *StdHeader
225 )
226{
227 UINT32 DeviceSSID;
228 UINTN MmioBase;
229 UINT32 MmioData3;
230
231 MmioBase = UserOptions.CfgTempPcieMmioBaseAddress;
232 if (MmioBase == 0) {
233 return GFX_WORKAROUND_SUCCESS;
234 }
235 GnbLibPciRMW (Device.AddressValue | 0x30, AccessWidth32, 0x0, ((UINT32)MmioBase) | 1, StdHeader);
236 GnbLibPciRMW (Device.AddressValue | 0x4, AccessWidth8, 0x0, 0x2, StdHeader);
237 GnbLibPciRead (Device.AddressValue | 0x2c, AccessWidth32, &DeviceSSID, StdHeader);
238 GnbLibMemRead (MmioBase + 0x54, AccessWidth32, &MmioData3, StdHeader);
239 if (DeviceSSID != MmioData3) {
240 GnbLibPciRMW (Device.AddressValue | 0x40, AccessWidth32, 0x0, MmioData3, StdHeader);
241 }
242 GnbLibPciRMW (Device.AddressValue | 0x30, AccessWidth32, 0x0, 0x0, StdHeader);
243 GnbLibPciRMW (Device.AddressValue | 0x4, AccessWidth8, 0x0, 0x0, StdHeader);
244 return GFX_WORKAROUND_SUCCESS;
245}
246
247/*----------------------------------------------------------------------------------------*/
248/**
249 * Allocate temporary resources for Pcie P2P bridge
250 *
251 *
252 *
253 * @param[in] Port Pci Address of Port to initialize.
254 * @param[in] StdHeader Standard configuration header
255 */
256AGESA_STATUS
257PcieConfigureBridgeResources (
258 IN PCI_ADDR Port,
259 IN AMD_CONFIG_PARAMS *StdHeader
260 )
261{
262 UINT32 Value;
263 UINT32 MmioBase;
264
265 MmioBase = UserOptions.CfgTempPcieMmioBaseAddress;
266 if (MmioBase == 0) {
267 return AGESA_WARNING;
268 }
269 Value = Port.Address.Bus + ((Port.Address.Bus + Port.Address.Device) << 8) + ((Port.Address.Bus + Port.Address.Device) << 16);
270 GnbLibPciWrite (Port.AddressValue | DxF0x18_ADDRESS, AccessWidth32, &Value, StdHeader);
271 Value = MmioBase + (MmioBase >> 16);
272 GnbLibPciWrite (Port.AddressValue | DxF0x20_ADDRESS, AccessWidth32, &Value, StdHeader);
273 Value = 0x000fff0;
274 GnbLibPciWrite (Port.AddressValue | DxF0x24_ADDRESS, AccessWidth32, &Value, StdHeader);
275 Value = 0x2;
276 GnbLibPciWrite (Port.AddressValue | 0x4 , AccessWidth8, &Value, StdHeader);
277 return AGESA_SUCCESS;
278}
279
280/*----------------------------------------------------------------------------------------*/
281/**
282 * Free temporary resources for Pcie P2P bridge
283 *
284 *
285 *
286 * @param[in] Port Pci Address of Port to clear resource allocation.
287 * @param[in] StdHeader Standard configuration header
288 */
289VOID
290PcieFreeBridgeResources (
291 IN PCI_ADDR Port,
292 IN AMD_CONFIG_PARAMS *StdHeader
293 )
294{
295 UINT32 Value;
296
297 Value = 0;
298 GnbLibPciWrite (Port.AddressValue | 0x4 , AccessWidth8, &Value, StdHeader);
299 GnbLibPciWrite (Port.AddressValue | DxF0x18_ADDRESS, AccessWidth32, &Value, StdHeader);
300 GnbLibPciWrite (Port.AddressValue | DxF0x20_ADDRESS, AccessWidth32, &Value, StdHeader);
301 GnbLibPciWrite (Port.AddressValue | DxF0x24_ADDRESS, AccessWidth32, &Value, StdHeader);
302
303}
304
305
306/*----------------------------------------------------------------------------------------*/
307/*
308 * Save CPU MMIO register
309 *
310 *
311 *
312 * @param[out] UINT32 SaveValues
313 * @param[in] StdHeader Standard configuration header
314 *
315 */
316VOID
317PcieProgramCpuMmio (
318 OUT UINT32 *SaveValues,
319 IN AMD_CONFIG_PARAMS *StdHeader
320 )
321{
322 //Save CPU MMIO Register
323 GnbLibPciRead (MAKE_SBDFO (0, 0, 0x18, 0x1, 0xB8), AccessWidth32, SaveValues, StdHeader);
324 GnbLibPciRead (MAKE_SBDFO (0, 0, 0x18, 0x1, 0xBC), AccessWidth32, SaveValues + 1, StdHeader);
325
326 //Write Temp Pcie MMIO to CPU
327 GnbLibPciRMW (MAKE_SBDFO (0, 0, 0x18, 0x1, 0xBC), AccessWidth32, 0, (UserOptions.CfgTempPcieMmioBaseAddress >> 16) << 8, StdHeader);
328 GnbLibPciRMW (MAKE_SBDFO (0, 0, 0x18, 0x1, 0xB8), AccessWidth32, 0, ((UserOptions.CfgTempPcieMmioBaseAddress >> 16) << 8) | 0x3, StdHeader);
329
330}
331
332/*----------------------------------------------------------------------------------------*/
333/*
334 * Restore CPU MMIO register
335 *
336 *
337 *
338 * @param[in] PCIe_PLATFORM_CONFIG Pcie
339 * @param[in] StdHeader Standard configuration header
340 */
341VOID
342PcieRestoreCpuMmio (
343 IN UINT32 *RestoreValues,
344 IN AMD_CONFIG_PARAMS *StdHeader
345 )
346{
347 //Restore CPU MMIO Register
348 GnbLibPciRMW (MAKE_SBDFO (0, 0, 0x18, 0x1, 0xB8), AccessWidth32, 0, *RestoreValues, StdHeader);
349 GnbLibPciRMW (MAKE_SBDFO (0, 0, 0x18, 0x1, 0xBC), AccessWidth32, 0, *(RestoreValues + 1), StdHeader);
350
351}
352
353/*----------------------------------------------------------------------------------------*/
354/*
355 * Check if card required test for deskew workaround
356 *
357 *
358 *
359 * @param[in] DeviceId Device ID
360 */
361
362BOOLEAN
363PcieIsDeskewCardDetected (
364 IN UINT16 DeviceId
365 )
366{
367 if ((DeviceId >= 0x3150 && DeviceId <= 0x3152) || (DeviceId == 0x3154) ||
368 (DeviceId == 0x3E50) || (DeviceId == 0x3E54) ||
369 ((DeviceId & 0xfff8) == 0x5460) || ((DeviceId & 0xfff8) == 0x5B60)) {
370 return TRUE;
371 }
372 return FALSE;
373}
374
375