blob: 9080571a6e7868bf72c3c5076ec58f68c4309b69 [file] [log] [blame]
zbao7d94cf92012-07-02 14:19:14 +08001/* $NoKeywords:$ */
2/**
3 * @file
4 *
5 * NB services
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 "heapManager.h"
54#include "Gnb.h"
55#include "GnbFuseTable.h"
56#include "GnbCommonLib.h"
57#include "GnbNbInitLibV1.h"
58#include "GnbRegistersLN.h"
59#include "OptionGnb.h"
60#include "Filecode.h"
61#define FILECODE PROC_GNB_MODULES_GNBNBINITLIBV1_GNBNBINITLIBV1_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 */
66extern GNB_BUILD_OPTIONS GnbBuildOptions;
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 */
72
73
74/*----------------------------------------------------------------------------------------
75 * 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
76 *----------------------------------------------------------------------------------------
77 */
78
79/*----------------------------------------------------------------------------------------*/
80/**
81 * Init NB set top of memory
82 *
83 *
84 *
85 * @param[in] NbPciAddress Gnb PCI address
86 * @param[in] StdHeader Standard Configuration Header
87 */
88
89AGESA_STATUS
90GnbSetTom (
91 IN PCI_ADDR NbPciAddress,
92 IN AMD_CONFIG_PARAMS *StdHeader
93 )
94{
95 AGESA_STATUS Status;
96 UINT64 MsrData;
97 UINT32 Value;
98 Status = AGESA_SUCCESS;
99 //Read memory size below 4G from MSR C001_001A
100 LibAmdMsrRead (TOP_MEM, &MsrData, StdHeader);
101 //Write to NB register 0x90
102 Value = (UINT32)MsrData & 0xFF800000; //Keep bits 31:23
103 GnbLibPciRMW (
104 NbPciAddress.AddressValue | D0F0x90_ADDRESS,
105 AccessS3SaveWidth32,
106 0x007FFFFF,
107 Value,
108 StdHeader
109 );
110 if (Value == 0) {
111 Status = AGESA_WARNING;
112 }
113
114 LibAmdMsrRead (SYS_CFG, &MsrData, StdHeader);
115 if ((MsrData & BIT21) != 0) {
116 //Read memory size above 4G from MSR C001_001D
117 LibAmdMsrRead (TOP_MEM2, &MsrData, StdHeader);
118 // Write memory size[39:32] to indirect register 1A[7:0]
119 Value = (UINT32) ((MsrData >> 32) & 0xFF);
120 GnbLibPciIndirectRMW (
121 NbPciAddress.AddressValue | D0F0x60_ADDRESS,
122 D0F0x64_x1A_ADDRESS | IOC_WRITE_ENABLE,
123 AccessS3SaveWidth32,
124 0xFFFFFF00,
125 Value,
126 StdHeader
127 );
128
129 // Write memory size[31:23] to indirect register 19[31:23] and enable memory through bit 0
130 Value = (UINT32)MsrData & 0xFF800000; //Keep bits 31:23
131 Value |= BIT0; // Enable top of memory
132 GnbLibPciIndirectRMW (
133 NbPciAddress.AddressValue | D0F0x60_ADDRESS,
134 D0F0x64_x19_ADDRESS | IOC_WRITE_ENABLE,
135 AccessS3SaveWidth32,
136 0x007FFFFF,
137 Value,
138 StdHeader
139 );
140 }
141 return Status;
142}
143
144
145/*----------------------------------------------------------------------------------------*/
146/**
147 * Avoid LPC DMA transaction deadlock
148 *
149 *
150 *
151 * @param[in] NbPciAddress Gnb PCI address
152 * @param[in] StdHeader Standard Configuration Header
153 */
154
155VOID
156GnbLpcDmaDeadlockPrevention (
157 IN PCI_ADDR NbPciAddress,
158 IN AMD_CONFIG_PARAMS *StdHeader
159 )
160{
161 // For GPP Link core, enable special NP memory write protocol on the processor side PCIE controller
162 GnbLibPciIndirectRMW (
163 NbPciAddress.AddressValue | D0F0xE0_ADDRESS,
164 CORE_SPACE (1, D0F0xE4_CORE_0010_ADDRESS),
165 AccessWidth32,
166 0xFFFFFFFF,
167 1 << 9 ,
168 StdHeader
169 );
170
171 //Enable special NP memory write protocol in ORB
172 GnbLibPciIndirectRMW (
173 NbPciAddress.AddressValue | D0F0x94_ADDRESS,
174 D0F0x98_x06_ADDRESS | (1 << D0F0x94_OrbIndWrEn_OFFSET),
175 AccessS3SaveWidth32,
176 0xFFFFFFFF,
177 1 << D0F0x98_x06_UmiNpMemWrEn_OFFSET,
178 StdHeader
179 );
180}
181
182/*----------------------------------------------------------------------------------------*/
183/**
184 * NB Dynamic Wake
185 * ORB_CNB_Wake signal is used to inform the CNB NCLK controller and GNB LCLK controller
186 * that ORB is (or will soon) push data into the synchronizer FIFO (i.e. wake is high).
187 *
188 * @param[in] NbPciAddress Gnb PCI address
189 * @param[in] StdHeader Standard Configuration Header
190 */
191
192VOID
193GnbOrbDynamicWake (
194 IN PCI_ADDR NbPciAddress,
195 IN AMD_CONFIG_PARAMS *StdHeader
196 )
197{
198
199 ex495_STRUCT ex495 ;
200
201 GnbLibPciIndirectRead (
202 NbPciAddress.AddressValue | D0F0x94_ADDRESS,
203 0x2c | (1 << D0F0x94_OrbIndWrEn_OFFSET),
204 AccessWidth32,
205 &ex495.Value,
206 StdHeader
207 );
208
209 // Enable Dynamic wake
210 // Wake Hysteresis timer value. Specifies the number of SMU pulses to count.
211 if (GnbBuildOptions.CfgOrbDynWakeEnable) {
212 ex495.Field.ex495_1 = 1;
213 } else {
214 ex495.Field.ex495_1 = 0;
215 }
216 ex495.Field.ex495_3 = 0x64;
217
218 IDS_OPTION_HOOK (IDS_GNB_ORBDYNAMIC_WAKE, &ex495, StdHeader);
219
220 GnbLibPciIndirectWrite (
221 NbPciAddress.AddressValue | D0F0x94_ADDRESS,
222 0x2c | (1 << D0F0x94_OrbIndWrEn_OFFSET),
223 AccessS3SaveWidth32,
224 &ex495.Value,
225 StdHeader
226 );
227}
228
229/*----------------------------------------------------------------------------------------*/
230/**
231 * Lock NB registers
232 *
233 *
234 *
235 * @param[in] NbPciAddress Gnb PCI address
236 * @param[in] StdHeader Standard Configuration Header
237 */
238
239VOID
240GnbLock (
241 IN PCI_ADDR NbPciAddress,
242 IN AMD_CONFIG_PARAMS *StdHeader
243 )
244{
245 GnbLibPciIndirectWriteField (
246 NbPciAddress.AddressValue | D0F0x60_ADDRESS,
247 D0F0x64_x00_ADDRESS | IOC_WRITE_ENABLE,
248 D0F0x64_x00_HwInitWrLock_OFFSET,
249 D0F0x64_x00_HwInitWrLock_WIDTH,
250 0x1,
251 TRUE,
252 StdHeader
253 );
254}
255
256
257/*----------------------------------------------------------------------------------------*/
258/**
259 * UnitID Clumping
260 *
261 *
262 * @param[in] NbPciAddress Gnb PCI address
263 * @param[in] StdHeader Standard Configuration Header
264 */
265
266VOID
267GnbClumpUnitID (
268 IN PCI_ADDR NbPciAddress,
269 IN AMD_CONFIG_PARAMS *StdHeader
270 )
271{
272 UINT32 Value;
273 GnbLibPciRead (MAKE_SBDFO (0, NbPciAddress.Address.Bus, 2, 0, 0), AccessWidth32, &Value, StdHeader);
274 if (Value != 0xFFFFFFFF) {
275 GnbLibPciRead (MAKE_SBDFO (0, NbPciAddress.Address.Bus, 3, 0, 0), AccessWidth32, &Value, StdHeader);
276 if (Value == 0xFFFFFFFF) {
277 GnbLibPciIndirectRMW (
278 NbPciAddress.AddressValue | D0F0x94_ADDRESS,
279 0x3a | (1 << D0F0x94_OrbIndWrEn_OFFSET),
280 AccessS3SaveWidth32,
281 0xFFFFFFFF,
282 1 << 3 /* D0F0x98_x3A_ClumpingEn_OFFSET*/,
283 StdHeader
284 );
285 }
286 }
287}
288
289/*----------------------------------------------------------------------------------------*/
290/**
291 * Get the index of highest SCLK VID
292 *
293 * @param[in] StdHeader Standard configuration header
294 * @retval NBVDD VID index
295 */
296UINT8
297GnbLocateHighestVidIndex (
298 IN AMD_CONFIG_PARAMS *StdHeader
299 )
300{
301 UINT8 MaxVid;
302 UINT8 MaxVidIndex;
303 UINTN Index;
304 PP_FUSE_ARRAY *PpFuseArray;
305
306 PpFuseArray = (PP_FUSE_ARRAY *) GnbLocateHeapBuffer (AMD_PP_FUSE_TABLE_HANDLE, StdHeader);
307 ASSERT (PpFuseArray != NULL);
308 if (PpFuseArray == NULL) {
309 IDS_HDT_CONSOLE (GNB_TRACE, " ERROR!!! Heap Location\n");
310 return 0;
311 }
312
313 MaxVidIndex = 0;
314 MaxVid = 0xff;
315 for (Index = 0; Index < 4; Index++) {
316 if (PpFuseArray->SclkVid[Index] != 0 && PpFuseArray->SclkVid[Index] < MaxVid) {
317 MaxVid = PpFuseArray->SclkVid[Index];
318 MaxVidIndex = (UINT8) Index;
319 }
320 }
321 ASSERT (PpFuseArray->SclkVid[MaxVidIndex] != 0);
322 return MaxVidIndex;
323}
324
325/*----------------------------------------------------------------------------------------*/
326/**
327 * Get the index of lowest SCLK VID
328 *
329 * @param[in] StdHeader Standard configuration header
330 * @retval NBVDD VID index
331 */
332UINT8
333GnbLocateLowestVidIndex (
334 IN AMD_CONFIG_PARAMS *StdHeader
335 )
336{
337 UINT8 MinVidIndex;
338 UINTN Index;
339 PP_FUSE_ARRAY *PpFuseArray;
340
341 PpFuseArray = (PP_FUSE_ARRAY *) GnbLocateHeapBuffer (AMD_PP_FUSE_TABLE_HANDLE, StdHeader);
342 ASSERT (PpFuseArray != NULL);
343 if (PpFuseArray == NULL) {
344 IDS_HDT_CONSOLE (GNB_TRACE, " ERROR!!! Heap Location\n");
345 return 0;
346 }
347
348 MinVidIndex = 0;
349
350 for (Index = 0; Index < 4; Index++) {
351 if (PpFuseArray->SclkVid[Index] > PpFuseArray->SclkVid[MinVidIndex]) {
352 MinVidIndex = (UINT8) Index;
353 }
354 }
355 ASSERT (PpFuseArray->SclkVid[MinVidIndex] != 0);
356 return MinVidIndex;
357}
358
359/*----------------------------------------------------------------------------------------*/
360/**
361 * Get the highest SCLK VID (high voltage)
362 *
363 * @param[in] StdHeader Standard configuration header
364 * @retval NBVDD VID
365 */
366UINT8
367GnbLocateHighestVidCode (
368 IN AMD_CONFIG_PARAMS *StdHeader
369 )
370{
371 UINT8 MaxVidIndex;
372 PP_FUSE_ARRAY *PpFuseArray;
373
374 PpFuseArray = (PP_FUSE_ARRAY *) GnbLocateHeapBuffer (AMD_PP_FUSE_TABLE_HANDLE, StdHeader);
375 ASSERT (PpFuseArray != NULL);
376
377 MaxVidIndex = GnbLocateHighestVidIndex (StdHeader);
378 ASSERT (PpFuseArray->SclkVid[MaxVidIndex] != 0);
379 return PpFuseArray->SclkVid[MaxVidIndex];
380
381}
382
383/*----------------------------------------------------------------------------------------*/
384/**
385 * Get the lowest SCLK VID (low voltage)
386 *
387 * @param[in] StdHeader Standard configuration header
388 * @retval NBVDD VID
389 */
390UINT8
391GnbLocateLowestVidCode (
392 IN AMD_CONFIG_PARAMS *StdHeader
393 )
394{
395 UINT8 MinVidIndex;
396 PP_FUSE_ARRAY *PpFuseArray;
397
398 PpFuseArray = (PP_FUSE_ARRAY *) GnbLocateHeapBuffer (AMD_PP_FUSE_TABLE_HANDLE, StdHeader);
399 ASSERT (PpFuseArray != NULL);
400 MinVidIndex = GnbLocateLowestVidIndex (StdHeader);
401 ASSERT (PpFuseArray->SclkVid[MinVidIndex] != 0);
402 return PpFuseArray->SclkVid[MinVidIndex];
403}
404
405