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