blob: 6e5d83daa21a32e79a264a00add89690a4e75744 [file] [log] [blame]
Frank Vibrans2b4c8312011-02-14 18:30:54 +00001/* $NoKeywords:$ */
2/**
3 * @file
4 *
5 * SMU access routine
6 *
7 *
8 *
9 * @xrefitem bom "File Content Label" "Release Content"
10 * @e project: AGESA
11 * @e sub-project: GNB
12 * @e \$Revision: 39275 $ @e \$Date: 2010-10-09 08:22:05 +0800 (Sat, 09 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 "amdlib.h"
53#include "Ids.h"
54#include "Gnb.h"
55#include GNB_MODULE_DEFINITIONS (GnbCommonLib)
56#include "OptionGnb.h"
57#include "NbSmuLib.h"
58#include "GnbRegistersON.h"
59#include "S3SaveState.h"
60#include "Filecode.h"
61#define FILECODE PROC_GNB_NB_NBSMULIB_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
67/// Efuse write packet
68typedef struct {
69 SMUx0B_x8600_STRUCT SMUx0B_x8600; ///< Reg SMUx0B_x8600
70 SMUx0B_x8604_STRUCT SMUx0B_x8604; ///< Reg SMUx0B_x8604
71 SMUx0B_x8608_STRUCT SMUx0B_x8608; ///< Reg SMUx0B_x8605
72} MBUS;
73
74
75/*----------------------------------------------------------------------------------------
76 * T Y P E D E F S A N D S T R U C T U R E S
77 *----------------------------------------------------------------------------------------
78 */
79
80/*----------------------------------------------------------------------------------------
81 * 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
82 *----------------------------------------------------------------------------------------
83 */
84
Frank Vibrans2b4c8312011-02-14 18:30:54 +000085/*----------------------------------------------------------------------------------------*/
86/**
87 * SMU indirect register read
88 *
89 *
90 *
91 * @param[in] Address Register Address
92 * @param[in] Width Data width for read
93 * @param[out] Value Pointer read value
94 * @param[in] StdHeader Pointer to standard configuration
95 */
96
97
98VOID
99NbSmuIndirectRead (
100 IN UINT8 Address,
101 IN ACCESS_WIDTH Width,
102 OUT VOID *Value,
103 IN AMD_CONFIG_PARAMS *StdHeader
104 )
105{
106
107 D0F0x64_x4D_STRUCT D0F0x64_x4D;
108 UINT32 Data;
109 GnbLibPciIndirectRead (
110 MAKE_SBDFO (0, 0, 0, 0, D0F0x60_ADDRESS),
111 D0F0x64_x4D_ADDRESS | IOC_WRITE_ENABLE,
112 AccessWidth32,
113 &D0F0x64_x4D.Value,
114 StdHeader
115 );
116
117 D0F0x64_x4D.Field.ReqType = 0;
118 D0F0x64_x4D.Field.SmuAddr = Address;
119 if (Width == AccessS3SaveWidth32 || Width == AccessWidth32) {
120 D0F0x64_x4D.Field.SmuAddr += 1;
121 }
122
123 D0F0x64_x4D.Field.ReqToggle = !D0F0x64_x4D.Field.ReqToggle;
124
125 GnbLibPciIndirectWrite (
126 MAKE_SBDFO (0, 0, 0, 0, D0F0x60_ADDRESS),
127 D0F0x64_x4D_ADDRESS | IOC_WRITE_ENABLE,
128 (Width >= AccessS3SaveWidth8) ? AccessS3SaveWidth32 : AccessWidth32,
129 &D0F0x64_x4D.Value,
130 StdHeader
131 );
132
133 GnbLibPciIndirectRead (
134 MAKE_SBDFO (0, 0, 0, 0, D0F0x60_ADDRESS),
135 D0F0x64_x4E_ADDRESS | IOC_WRITE_ENABLE,
136 (Width >= AccessS3SaveWidth8) ? AccessS3SaveWidth32 : AccessWidth32,
137 &Data,
138 StdHeader
139 );
140
141 switch (Width) {
142 case AccessWidth16:
143 //no break; intended to fall through
144 case AccessS3SaveWidth16:
145 *(UINT16 *) Value = (UINT16) Data;
146 break;
147 case AccessWidth32:
148 //no break; intended to fall through
149 case AccessS3SaveWidth32:
150 *(UINT32 *) Value = Data;
151 break;
152 default:
153 ASSERT (FALSE);
154 }
155}
156
157/*----------------------------------------------------------------------------------------*/
158/**
159 * SMU indirect register read
160 *
161 *
162 *
163 * @param[in] Address Register Address
164 * @param[in] Width Access width
165 * @param[in] Mask Data mask for compare
166 * @param[in] CompateData Compare data
167 * @param[in] StdHeader Pointer to standard configuration
168 */
169
170
171VOID
172NbSmuIndirectPoll (
173 IN UINT8 Address,
174 IN ACCESS_WIDTH Width,
175 IN UINT32 Mask,
176 IN UINT32 CompateData,
177 IN AMD_CONFIG_PARAMS *StdHeader
178 )
179{
180 UINT32 Value;
181
182 do {
183 NbSmuIndirectRead (
184 Address,
185 Width,
186 &Value,
187 StdHeader
188 );
189 } while ((Value & Mask) != CompateData);
190}
191
192
193/*----------------------------------------------------------------------------------------*/
194/**
195 * SMU indirect register write
196 *
197 *
198 *
199 * @param[in] Address Register Address
200 * @param[in] Width Data width for write
201 * @param[in] Value Pointer to write value
202 * @param[in] StdHeader Pointer to standard configuration
203 */
204
205
206VOID
207NbSmuIndirectWriteEx (
208 IN UINT8 Address,
209 IN ACCESS_WIDTH Width,
Arthur Heymans704ccaf2022-05-16 14:55:46 +0200210 CONST IN VOID *Value,
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000211 IN AMD_CONFIG_PARAMS *StdHeader
212 )
213{
214 D0F0x64_x4D_STRUCT D0F0x64_x4D;
215 ASSERT (Width != AccessWidth8);
216 ASSERT (Width != AccessS3SaveWidth8);
217
218 GnbLibPciIndirectRead (
219 MAKE_SBDFO (0, 0, 0, 0, D0F0x60_ADDRESS),
220 D0F0x64_x4D_ADDRESS | IOC_WRITE_ENABLE,
221 AccessWidth32,
222 &D0F0x64_x4D.Value,
223 StdHeader
224 );
225
226 D0F0x64_x4D.Field.ReqType = 0x1;
227 D0F0x64_x4D.Field.SmuAddr = Address;
228 D0F0x64_x4D.Field.ReqToggle = (!D0F0x64_x4D.Field.ReqToggle);
229
230 D0F0x64_x4D.Field.WriteData = ((UINT16 *) Value) [0];
231
232 GnbLibPciIndirectWrite (
233 MAKE_SBDFO (0, 0, 0, 0, D0F0x60_ADDRESS),
234 D0F0x64_x4D_ADDRESS | IOC_WRITE_ENABLE,
235 (Width >= AccessS3SaveWidth8) ? AccessS3SaveWidth32 : AccessWidth32,
236 &D0F0x64_x4D.Value,
237 StdHeader
238 );
239 if (LibAmdAccessWidth (Width) <= 2) {
240 return;
241 }
242 D0F0x64_x4D.Field.ReqType = 0x1;
243 D0F0x64_x4D.Field.SmuAddr = Address + 1;
244 D0F0x64_x4D.Field.ReqToggle = (!D0F0x64_x4D.Field.ReqToggle);
245 D0F0x64_x4D.Field.WriteData = ((UINT16 *) Value)[1];
246
247 GnbLibPciIndirectWrite (
248 MAKE_SBDFO (0, 0, 0, 0, D0F0x60_ADDRESS),
249 D0F0x64_x4D_ADDRESS | IOC_WRITE_ENABLE,
250 (Width >= AccessS3SaveWidth8) ? AccessS3SaveWidth32 : AccessWidth32,
251 &D0F0x64_x4D.Value,
252 StdHeader
253 );
254}
255
256
257/*----------------------------------------------------------------------------------------*/
258/**
259 * SMU indirect register write
260 *
261 *
262 *
263 * @param[in] Address Register Address
264 * @param[in] Width Data width for write
265 * @param[in] Value Pointer to write value
266 * @param[in] StdHeader Pointer to standard configuration
267 */
268
269
270VOID
271NbSmuIndirectWrite (
272 IN UINT8 Address,
273 IN ACCESS_WIDTH Width,
Arthur Heymans704ccaf2022-05-16 14:55:46 +0200274 CONST IN VOID *Value,
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000275 IN AMD_CONFIG_PARAMS *StdHeader
276 )
277{
278 if (Width >= AccessS3SaveWidth8) {
279 SMU_INDIRECT_WRITE_DATA Data;
280 Data.Address = Address;
281 Data.Width = Width;
282 Data.Value = *((UINT32*) Value);
283 S3_SAVE_DISPATCH (StdHeader, S3DispatchGnbSmuIndirectWrite, sizeof (SMU_INDIRECT_WRITE_DATA), &Data);
284 Width = Width - (AccessS3SaveWidth8 - AccessWidth8);
285 }
286 NbSmuIndirectWriteEx (Address, Width, Value, StdHeader);
287}
288
289
290/*----------------------------------------------------------------------------------------*/
291/**
292 * SMU Service request for S3 script
293 *
294 *
295 * @param[in] StdHeader Standard configuration header
296 * @param[in] ContextLength Not used
297 * @param[in] Context Pointer to service request ID
298 */
299
300VOID
301NbSmuIndirectWriteS3Script (
302 IN AMD_CONFIG_PARAMS *StdHeader,
303 IN UINT16 ContextLength,
304 IN VOID* Context
305 )
306{
307 SMU_INDIRECT_WRITE_DATA *Data;
308 Data = (SMU_INDIRECT_WRITE_DATA*) Context;
309 NbSmuIndirectWriteEx (Data->Address, Data->Width, &Data->Value, StdHeader);
310}
311
312/*----------------------------------------------------------------------------------------*/
313/**
314 * SMU RAM mapped register write
315 *
316 *
317 *
318 * @param[in] Address Register Address
319 * @param[in] Value Data pointer for write
320 * @param[in] Count Number of registers to write
321 * @param[in] S3Save Save for S3 (True/False)
322 * @param[in] StdHeader Standard configuration header
323 */
324
325VOID
326NbSmuRcuRegisterWrite (
327 IN UINT16 Address,
Arthur Heymans704ccaf2022-05-16 14:55:46 +0200328 CONST IN UINT32 *Value,
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000329 IN UINT32 Count,
330 IN BOOLEAN S3Save,
331 IN AMD_CONFIG_PARAMS *StdHeader
332 )
333{
334 UINT32 CurrentAddress;
335 CurrentAddress = Address;
336 NbSmuIndirectWrite (
337 SMUx0B_ADDRESS,
338 S3Save ? AccessS3SaveWidth16 : AccessWidth16,
339 &Address,
340 StdHeader
341 );
342 while (Count-- > 0) {
343 IDS_HDT_CONSOLE (NB_SMUREG_TRACE, " *WR SMUx0B:0x%x = 0x%x\n", CurrentAddress, *Value);
344 NbSmuIndirectWrite (
345 SMUx05_ADDRESS,
346 S3Save ? AccessS3SaveWidth32 : AccessWidth32,
347 Value++,
348 StdHeader
349 );
350 CurrentAddress += 4;
351 }
352}
353
354
355/*----------------------------------------------------------------------------------------*/
356/**
357 * SMU RAM mapped register read
358 *
359 *
360 *
361 * @param[in] Address Register Address
362 * @param[out] Value Pointer read value
363 * @param[in] Count Number of registers to read
364 * @param[in] StdHeader Pointer to standard configuration
365 */
366
367VOID
368NbSmuRcuRegisterRead (
369 IN UINT16 Address,
370 OUT UINT32 *Value,
371 IN UINT32 Count,
372 IN AMD_CONFIG_PARAMS *StdHeader
373 )
374{
375 NbSmuIndirectWrite (SMUx0B_ADDRESS, AccessWidth16, &Address, StdHeader);
376 while (Count-- > 0) {
377 NbSmuIndirectRead (SMUx05_ADDRESS, AccessWidth32, Value++, StdHeader);
378 }
379}
380
381
382/*----------------------------------------------------------------------------------------*/
383/**
384 * SMU Service request Ext
385 *
386 *
387 * @param[in] RequestId request ID
388 * @param[in] Flags Flags
389 * @param[in] StdHeader Standard configuration header
390 */
391
392VOID
393NbSmuServiceRequestEx (
394 IN UINT8 RequestId,
395 IN UINT8 Flags,
396 IN AMD_CONFIG_PARAMS *StdHeader
397 )
398{
399 SMUx03_STRUCT SMUx03;
400 SMUx03.Value = 0;
401 SMUx03.Field.IntReq = 1;
402 SMUx03.Field.ServiceIndex = RequestId;
403 NbSmuIndirectWrite (SMUx03_ADDRESS, AccessWidth32, &SMUx03.Value, StdHeader);
404 if ((Flags & SMU_EXT_SERVICE_FLAGS_POLL_ACK) != 0) {
405 NbSmuIndirectPoll (SMUx03_ADDRESS, AccessWidth32, BIT1, BIT1, StdHeader); // Wait till IntAck
406 }
407 if ((Flags & SMU_EXT_SERVICE_FLAGS_POLL_DONE) != 0) {
408 NbSmuIndirectPoll (SMUx03_ADDRESS, AccessWidth32, BIT2, BIT2, StdHeader); // Wait till IntDone
409 }
410 SMUx03.Value = 0; // Clear IRQ register
411 NbSmuIndirectWrite (SMUx03_ADDRESS, AccessWidth32, &SMUx03.Value, StdHeader);
412}
413
414/*----------------------------------------------------------------------------------------*/
415/**
416 * SMU Service request
417 *
418 *
419 * @param[in] RequestId request ID
420 * @param[in] S3Save Save for S3 (True/False)
421 * @param[in] StdHeader Standard configuration header
422 */
423
424VOID
425NbSmuServiceRequest (
426 IN UINT8 RequestId,
427 IN BOOLEAN S3Save,
428 IN AMD_CONFIG_PARAMS *StdHeader
429 )
430{
431 IDS_HDT_CONSOLE (GNB_TRACE, "NbSmuServiceRequest Enter [0x%02x]\n", RequestId);
432 if (S3Save) {
433 S3_SAVE_DISPATCH (StdHeader, S3DispatchGnbSmuServiceRequest, sizeof (RequestId), &RequestId);
434 }
435 NbSmuServiceRequestEx (
436 RequestId,
437 SMU_EXT_SERVICE_FLAGS_POLL_ACK | SMU_EXT_SERVICE_FLAGS_POLL_DONE,
438 StdHeader
439 );
440 IDS_HDT_CONSOLE (GNB_TRACE, "NbSmuServiceRequest Exit\n");
441}
442
443/*----------------------------------------------------------------------------------------*/
444/**
445 * SMU Service request for S3 script
446 *
447 *
448 * @param[in] StdHeader Standard configuration header
449 * @param[in] ContextLength Not used
450 * @param[in] Context Pointer to service request ID
451 */
452
453VOID
454NbSmuServiceRequestS3Script (
455 IN AMD_CONFIG_PARAMS *StdHeader,
456 IN UINT16 ContextLength,
457 IN VOID* Context
458 )
459{
460 NbSmuServiceRequest (*((UINT8*) Context), FALSE, StdHeader);
461}
462
463/*----------------------------------------------------------------------------------------*/
464/**
465 * SMU Read FCR register
466 *
467 *
468 * @param[in] Address FCR Address
469 * @param[in] StdHeader Standard configuration header
470 */
471
472UINT32
473NbSmuReadEfuse (
474 IN UINT32 Address,
475 IN AMD_CONFIG_PARAMS *StdHeader
476 )
477{
478 UINT32 Value;
479
480 NbSmuSrbmRegisterRead (Address, &Value, StdHeader);
481 Value = (Value >> 24) | (Value << 24) | ((Value >> 8) & 0xFF00) | ((Value << 8) & 0xFF0000);
482 return Value;
483}
484
485/*----------------------------------------------------------------------------------------*/
486/**
487 * SMU Read arbitrary fuse field
488 *
489 *
490 * @param[in] Chain Address
491 * @param[in] Offset Offcet
492 * @param[in] Length Length
493 * @param[in] StdHeader Standard configuration header
494 */
495
496UINT32
497NbSmuReadEfuseField (
498 IN UINT8 Chain,
499 IN UINT16 Offset,
500 IN UINT8 Length,
501 IN AMD_CONFIG_PARAMS *StdHeader
502 )
503{
504 UINT32 Value;
505 UINT32 Result;
506 UINT32 Address;
507 UINT16 Shift;
508 ASSERT (Length <= 32);
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000509 Shift = (Offset - (Offset & ~0x7));
510 Address = 0xFE000000 | (Chain << 12) | (Offset >> 3);
511 Value = NbSmuReadEfuse (Address, StdHeader);
512 Result = Value >> Shift;
513 if ((Shift + Length) > 32) {
514 Value = NbSmuReadEfuse (Address + 1, StdHeader);
515 Result |= (Value << (32 - Shift));
516 }
517 Result &= ((1 << Length) - 1);
518 return Value;
519}
520
521/*----------------------------------------------------------------------------------------*/
522/**
523 * SMU SRBM (GMM) register read
524 *
525 *
526 *
527 * @param[in] Address Register Address
528 * @param[out] Value Pointer read value
529 * @param[in] StdHeader Pointer to standard configuration
530 */
531
532VOID
533NbSmuSrbmRegisterRead (
534 IN UINT32 Address,
535 OUT UINT32 *Value,
536 IN AMD_CONFIG_PARAMS *StdHeader
537 )
538{
539 MBUS Mbus;
540 Mbus.SMUx0B_x8600.Value = (0x8650 << SMUx0B_x8600_MemAddr_7_0__OFFSET) |
541 (1 << SMUx0B_x8600_TransactionCount_OFFSET);
542 Mbus.SMUx0B_x8604.Value = (4 << SMUx0B_x8604_Txn1TransferLength_7_0__OFFSET);
543 Mbus.SMUx0B_x8608.Value = (UINT32) (3 << SMUx0B_x8608_Txn1Tsize_OFFSET);
544 Mbus.SMUx0B_x8600.Field.Txn1MBusAddr_7_0_ = Address & 0xff;
545 Mbus.SMUx0B_x8604.Field.Txn1MBusAddr_15_8_ = (Address >> 8) & 0xff;
546 Mbus.SMUx0B_x8604.Field.Txn1MBusAddr_23_16_ = (Address >> 16) & 0xff;
547 Mbus.SMUx0B_x8604.Field.Txn1MBusAddr_31_24_ = (Address >> 24) & 0xff;
548 NbSmuRcuRegisterWrite (SMUx0B_x8600_ADDRESS, (UINT32*) &Mbus, 3, FALSE, StdHeader);
549 NbSmuServiceRequest (0x0B, FALSE, StdHeader);
550 NbSmuRcuRegisterRead (SMUx0B_x8650_ADDRESS, Value, 1, StdHeader);
551}
552
553/*----------------------------------------------------------------------------------------*/
554/**
555 * SMU SRBM (GMM) register write
556 *
557 *
558 *
559 * @param[in] Address Register Address
560 * @param[in] Value Data pointer for write
561 * @param[in] S3Save Save for S3 (True/False)
562 * @param[in] StdHeader Standard configuration header
563 */
564
565VOID
566NbSmuSrbmRegisterWrite (
567 IN UINT32 Address,
568 IN UINT32 *Value,
569 IN BOOLEAN S3Save,
570 IN AMD_CONFIG_PARAMS *StdHeader
571 )
572{
573 MBUS Mbus;
574 IDS_HDT_CONSOLE (NB_SMUREG_TRACE, " *WR SRBM (GMM):0x%x = 0x%x\n", Address, *Value);
575 Mbus.SMUx0B_x8600.Value = (0x8650 << SMUx0B_x8600_MemAddr_7_0__OFFSET) |
576 (1 << SMUx0B_x8600_TransactionCount_OFFSET);
577 Mbus.SMUx0B_x8604.Value = (4 << SMUx0B_x8604_Txn1TransferLength_7_0__OFFSET);
578 Mbus.SMUx0B_x8608.Value = (UINT32) (3 << SMUx0B_x8608_Txn1Tsize_OFFSET);
579 Mbus.SMUx0B_x8608.Field.Txn1Mode = 0x1;
580 Mbus.SMUx0B_x8600.Field.Txn1MBusAddr_7_0_ = Address & 0xff;
581 Mbus.SMUx0B_x8604.Field.Txn1MBusAddr_15_8_ = (Address >> 8) & 0xff;
582 Mbus.SMUx0B_x8604.Field.Txn1MBusAddr_23_16_ = (Address >> 16) & 0xff;
583 Mbus.SMUx0B_x8604.Field.Txn1MBusAddr_31_24_ = (Address >> 24) & 0xff;
584 NbSmuRcuRegisterWrite (SMUx0B_x8600_ADDRESS, (UINT32*) &Mbus, 3, S3Save, StdHeader);
585 NbSmuRcuRegisterWrite (SMUx0B_x8650_ADDRESS, Value, 1, S3Save, StdHeader);
586 NbSmuServiceRequest (0x0B, S3Save, StdHeader);
587}
588
589/*----------------------------------------------------------------------------------------*/
590/**
591 * SMU firmware download
592 *
593 *
594 *
595 * @param[in] StdHeader Pointer to Standard configuration
596 * @param[in] Firmware Pointer to SMU firmware header
597 * @retval AGESA_STATUS
598 */
599
600VOID
601NbSmuFirmwareDownload (
Arthur Heymans704ccaf2022-05-16 14:55:46 +0200602 CONST SMU_FIRMWARE_HEADER *Firmware,
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000603 IN AMD_CONFIG_PARAMS *StdHeader
604 )
605{
606 UINTN Index;
607 SMUx01_STRUCT SMUx01;
608 NbSmuServiceRequestEx (0x10, SMU_EXT_SERVICE_FLAGS_POLL_ACK , StdHeader);
609 SMUx01.Value = (1 << SMUx01_RamSwitch_OFFSET) | (1 << SMUx01_VectorOverride_OFFSET);
610 NbSmuIndirectWrite (SMUx01_ADDRESS, AccessWidth32, &SMUx01.Value, StdHeader);
611 for (Index = 0; Index < Firmware->NumberOfBlock; Index++) {
612 NbSmuRcuRegisterWrite (
613 (Firmware->BlockArray)[Index].Address,
614 (Firmware->BlockArray)[Index].Data,
615 (Firmware->BlockArray)[Index].Length,
616 FALSE,
617 StdHeader
618 );
619 }
620 SMUx01.Value = (1 << SMUx01_Reset_OFFSET) | (1 << SMUx01_VectorOverride_OFFSET);
621 NbSmuIndirectWrite (SMUx01_ADDRESS, AccessWidth32, &SMUx01.Value, StdHeader);
622}
623
624/*----------------------------------------------------------------------------------------*/
625/**
626 * SMU firmware revision
627 *
628 *
629 *
630 * @param[in] StdHeader Pointer to Standard configuration
631 * @retval Firmware revision info
632 */
633
634SMU_FIRMWARE_REV
635NbSmuFirmwareRevision (
636 IN AMD_CONFIG_PARAMS *StdHeader
637 )
638{
639 SMU_FIRMWARE_REV Revision;
640 UINT32 FmRev;
641 NbSmuRcuRegisterRead (
642 0x830C,
643 &FmRev,
644 1,
645 StdHeader
646 );
647 Revision.MajorRev = ((UINT16*)&FmRev) [1];
648 Revision.MinorRev = ((UINT16*)&FmRev) [0];
649 return Revision;
650}