RD890 Northbridge: AMD RD890/SR56X0 Northbridge CIMX code
[coreboot.git] / src / vendorcode / amd / cimx / rd890 / nbLib.c
1 /**
2  * @file
3  *
4  * NB library functions.
5  *
6  *
7  *
8  * @xrefitem bom "File Content Label" "Release Content"
9  * @e project:      CIMx-NB
10  * @e sub-project:
11  * @e \$Revision:$   @e \$Date:$
12  *
13  */
14 /*****************************************************************************
15  *
16  * Copyright (C) 2012 Advanced Micro Devices, Inc.
17  * All rights reserved.
18  *
19  * Redistribution and use in source and binary forms, with or without
20  * modification, are permitted provided that the following conditions are met:
21  *     * Redistributions of source code must retain the above copyright
22  *       notice, this list of conditions and the following disclaimer.
23  *     * Redistributions in binary form must reproduce the above copyright
24  *       notice, this list of conditions and the following disclaimer in the
25  *       documentation and/or other materials provided with the distribution.
26  *     * Neither the name of Advanced Micro Devices, Inc. nor the names of
27  *       its contributors may be used to endorse or promote products derived
28  *       from this software without specific prior written permission.
29  *
30  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
31  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
33  * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
34  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
35  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
37  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
39  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40  *
41  *
42  ***************************************************************************/
43 /*----------------------------------------------------------------------------------------
44  *                             M O D U L E S    U S E D
45  *----------------------------------------------------------------------------------------
46  */
47
48 #include "NbPlatform.h"
49 #include "amdDebugOutLib.h"
50
51 /*----------------------------------------------------------------------------------------
52  *                   D E F I N I T I O N S    A N D    M A C R O S
53  *----------------------------------------------------------------------------------------
54  */
55
56
57 /*----------------------------------------------------------------------------------------
58  *                  T Y P E D E F S     A N D     S T R U C T U  R E S
59  *----------------------------------------------------------------------------------------
60  */
61
62 /*----------------------------------------------------------------------------------------
63  *           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
64  *----------------------------------------------------------------------------------------
65  */
66
67 /*----------------------------------------------------------------------------------------
68  *                          E X P O R T E D    F U N C T I O N S
69  *----------------------------------------------------------------------------------------
70  */
71
72 /*----------------------------------------------------------------------------------------*/
73 /**
74  * Get silicon type and revision info.
75  *
76  *
77  *
78  * @param[in]   NbConfigPtr configuration structure pointer.
79  * @retval      NB_INFO Northbrige Info Structure.
80  */
81 /*----------------------------------------------------------------------------------------*/
82 NB_INFO
83 LibNbGetRevisionInfo (
84   IN      AMD_NB_CONFIG   *NbConfigPtr
85   )
86 {
87   NB_INFO RevisionInfo;
88   UINT16  DeviceId;
89   UINT8   RevisionId;
90   UINT32  PrivateId;
91   LibNbPciRead (NbConfigPtr->NbPciAddress.AddressValue | 0x8, AccessWidth8, &RevisionId, NbConfigPtr);
92   RevisionInfo.Revision = RevisionId;
93   LibNbPciRead (NbConfigPtr->NbPciAddress.AddressValue | 0x2, AccessWidth16, &DeviceId, NbConfigPtr);
94   switch (DeviceId) {
95   case  0x5956:
96     RevisionInfo.Type = NB_RD890TV;
97     break;
98   case  0x5957:
99     RevisionInfo.Type = NB_RX780;
100     break;
101   case  0x5958:
102     RevisionInfo.Type = NB_RD780;
103     break;
104   case  0x5A10:
105     RevisionInfo.Type = NB_SR5690;
106     break;
107   case  0x5A11:
108     RevisionInfo.Type = NB_RD890;
109     break;
110   case  0x5A12:
111     RevisionInfo.Type = NB_SR5670;
112     break;
113   case  0x5A13:
114     RevisionInfo.Type = NB_SR5650;
115     break;
116   case  0x5A14:
117     RevisionInfo.Type = NB_990FX;
118     LibNbPciIndexRead (NbConfigPtr->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG7D, AccessWidth32, &PrivateId, NbConfigPtr);
119     PrivateId = (PrivateId >> 21) & 0x0f;
120     if (PrivateId == 1) {
121       RevisionInfo.Type = NB_990FX;
122     }
123     if (PrivateId == 2) {
124       RevisionInfo.Type = NB_990X;
125     }
126     if (PrivateId == 3) {
127       RevisionInfo.Type = NB_970;
128     }
129     break;
130   default:
131     RevisionInfo.Type = NB_UNKNOWN;
132     CIMX_ASSERT (FALSE);
133   }
134   return  RevisionInfo;
135 }
136
137 /*----------------------------------------------------------------------------------------*/
138 /**
139  * Call Back routine.
140  *
141  *
142  *
143  * @param[in] CallBackId   Callback ID.
144  * @param[in] Data         Callback specific data.
145  * @param[in] NbConfigPtr  Northbridge configuration structure pointer.
146  */
147 /*----------------------------------------------------------------------------------------*/
148 AGESA_STATUS
149 LibNbCallBack (
150   IN       UINT32          CallBackId,
151   IN OUT   UINTN           Data,
152   IN OUT   AMD_NB_CONFIG   *NbConfigPtr
153   )
154 {
155   AGESA_STATUS  Status;
156   CALLOUT_ENTRY CallBackPtr = GET_BLOCK_CONFIG_PTR (NbConfigPtr)->StandardHeader.CalloutPtr;
157
158   Status = AGESA_UNSUPPORTED;
159   if (CallBackPtr != NULL) {
160     CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (NbConfigPtr), CIMX_NB_TRACE), "[NBLIB]LibNbCallBack CallBackId = 0x%x\n", CallBackId));
161     Status = (*CallBackPtr) (CallBackId, Data, GET_BLOCK_CONFIG_PTR (NbConfigPtr));
162     CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (NbConfigPtr), CIMX_NB_TRACE), "[NBLIB]LibNbCallBack Return = 0x%x\n", Status));
163   }
164   return Status;
165 }
166
167
168 /*----------------------------------------------------------------------------------------*/
169 /**
170  * Call Back routine.
171  *
172  *
173  *
174  * @param[in] SystemApi    Pointer to System API
175  * @param[in] ConfigPtr  Northbridge block configuration structure pointer.
176  */
177 /*----------------------------------------------------------------------------------------*/
178 AGESA_STATUS
179 LibSystemApiCall (
180   IN       SYSTEM_API             SystemApi,
181   IN OUT   AMD_NB_CONFIG_BLOCK   *ConfigPtr
182   )
183 {
184   API_WORKSPACE Workspace;
185   UINT8         NorthbridgeId;
186
187   LibAmdMemFill (&Workspace, 0, sizeof (API_WORKSPACE), (AMD_CONFIG_PARAMS *)&(ConfigPtr->StandardHeader));
188   Workspace.ConfigPtr = ConfigPtr;
189   Workspace.Status = AGESA_SUCCESS;
190   for (NorthbridgeId = 0; NorthbridgeId <= ConfigPtr->NumberOfNorthbridges; NorthbridgeId++) {
191     ConfigPtr->Northbridges[NorthbridgeId].ConfigPtr = &Workspace.ConfigPtr;
192   }
193   if (SystemApi != NULL) {
194     (*SystemApi)(ConfigPtr);
195   }
196   return Workspace.Status;
197 }
198
199 /*----------------------------------------------------------------------------------------*/
200 /**
201  * Call Back routine.
202  *
203  *
204  *
205  * @param[in] NbApi       Pointer to NB API
206  * @param[in] ConfigPtr   Northbridge block configuration structure pointer
207  */
208 /*----------------------------------------------------------------------------------------*/
209 AGESA_STATUS
210 LibNbApiCall (
211   IN       NB_API                NbApi,
212   IN OUT   AMD_NB_CONFIG_BLOCK   *ConfigPtr
213   )
214 {
215   UINT8         NorthbridgeId;
216   AGESA_STATUS  Status;
217
218   Status = AGESA_SUCCESS;
219   for (NorthbridgeId = 0; NorthbridgeId <= ConfigPtr->NumberOfNorthbridges; NorthbridgeId++) {
220     AMD_NB_CONFIG *NbConfigPtr = &ConfigPtr->Northbridges[NorthbridgeId];
221     ConfigPtr->CurrentNorthbridge = NorthbridgeId;
222     if (!LibNbIsDevicePresent (NbConfigPtr->NbPciAddress, NbConfigPtr)) {
223       REPORT_EVENT (AGESA_WARNING, GENERAL_ERROR_NB_NOT_PRESENT, 0 , 0, 0, 0, NbConfigPtr);
224       continue;
225     }
226     if (NbApi != NULL) {
227       Status = (*NbApi) (NbConfigPtr);
228       if (Status == AGESA_FATAL) {
229         break;
230       }
231     }
232   }
233   return Status;
234 }
235
236 /*----------------------------------------------------------------------------------------*/
237 /**
238  * Write PCI register.
239  *
240  *
241  *
242  * @param[in] Address     Compressed PCIE address identical to PCI_ADDR.AddressValue
243  * @param[in] Width       Access width.
244  * @param[in] Value       Pointer to new register value.
245  * @param[in] NbConfigPtr Northbridge configuration structure pointer.
246  */
247 /*----------------------------------------------------------------------------------------*/
248
249 VOID
250 LibNbPciWrite (
251   IN      UINT32          Address,
252   IN      ACCESS_WIDTH    Width,
253   IN      VOID            *Value,
254   IN      AMD_NB_CONFIG   *NbConfigPtr
255   )
256 {
257   PCI_ADDR  DeviceAddress;
258   DeviceAddress.AddressValue = Address;
259   LibAmdPciWrite (Width, DeviceAddress, Value, (AMD_CONFIG_PARAMS *)((NbConfigPtr == NULL)?NULL:GET_BLOCK_CONFIG_PTR (NbConfigPtr)));
260 }
261
262
263 /*----------------------------------------------------------------------------------------*/
264 /**
265  * Read PCI register
266  *
267  *
268  *
269  * @param[in] Address     Compressed PCIE address identical to PCI_ADDR.AddressValue
270  * @param[in] Width       Access width.
271  * @param[in] Value       Pointer to save register value.
272  * @param[in] NbConfigPtr Northbridge configuration structure pointer.
273  *
274  */
275 /*----------------------------------------------------------------------------------------*/
276 VOID
277 LibNbPciRead (
278   IN       UINT32         Address,
279   IN       ACCESS_WIDTH   Width,
280      OUT   VOID           *Value,
281   IN       AMD_NB_CONFIG  *NbConfigPtr
282   )
283 {
284   PCI_ADDR  DeviceAddress;
285   DeviceAddress.AddressValue = Address;
286   LibAmdPciRead (Width, DeviceAddress, Value, (AMD_CONFIG_PARAMS *)((NbConfigPtr == NULL)?NULL:GET_BLOCK_CONFIG_PTR (NbConfigPtr)));
287 }
288
289 /*----------------------------------------------------------------------------------------*/
290 /**
291  * Read/Modify/Write  PCI register
292  *
293  *
294  *
295  * @param[in] Address     Compressed PCIE address identical to PCI_ADDR.AddressValue
296  * @param[in] Width       Access width.
297  * @param[in] Mask        AND Mask.
298  * @param[in] Data        OR Mask.
299  * @param[in] NbConfigPtr Northbridge configuration structure pointer.
300  */
301 /*----------------------------------------------------------------------------------------*/
302 VOID
303 LibNbPciRMW (
304   IN       UINT32         Address,
305   IN       ACCESS_WIDTH   Width,
306   IN       UINT32         Mask,
307   IN       UINT32         Data,
308   IN       AMD_NB_CONFIG  *NbConfigPtr
309   )
310 {
311   UINT32  Value;
312   LibNbPciRead (Address,  Width, &Value, NbConfigPtr);
313   Value = (Value & Mask) | Data;
314   LibNbPciWrite (Address, Width, &Value, NbConfigPtr);
315 }
316
317 /*----------------------------------------------------------------------------------------*/
318 /**
319  * Read PCI Index/Data Address space
320  *
321  *
322  *
323  * @param[in] Address     Compressed PCIE address identical to PCI_ADDR.AddressValue
324  * @param[in] Index       Index Address.
325  * @param[in] Width       Access width of Index/Data register.
326  * @param[in] Value       Pointer to save register value.
327  * @param[in] NbConfigPtr Northbridge configuration structure pointer.
328  */
329 /*----------------------------------------------------------------------------------------*/
330
331 VOID
332 LibNbPciIndexRead (
333   IN       UINT32        Address,
334   IN       UINT32        Index,
335   IN       ACCESS_WIDTH  Width,
336      OUT   UINT32        *Value,
337   IN       AMD_NB_CONFIG *NbConfigPtr
338   )
339 {
340   UINT32  IndexOffset;
341   IndexOffset = (1 << ((Width < 0x80)? (Width - 1): (Width - 0x81)));
342   LibNbPciWrite (Address, Width, &Index, NbConfigPtr);
343   LibNbPciRead (Address + IndexOffset, Width, Value, NbConfigPtr);
344 }
345
346 /*----------------------------------------------------------------------------------------*/
347 /**
348  * Write PCI Index/Data Address space
349  *
350  *
351  *
352  * @param[in] Address     Compressed PCIE address identical to PCI_ADDR.AddressValue
353  * @param[in] Index       Index Address.
354  * @param[in] Width       Access width of Index/Data register.
355  * @param[in] Value       Pointer to save register value.
356  * @param[in] NbConfigPtr Northbridge configuration structure pointer.
357  */
358 /*----------------------------------------------------------------------------------------*/
359
360 VOID
361 LibNbPciIndexWrite (
362   IN      UINT32        Address,
363   IN      UINT32        Index,
364   IN      ACCESS_WIDTH  Width,
365   IN      UINT32        *Value,
366   IN      AMD_NB_CONFIG *NbConfigPtr
367   )
368 {
369   UINT32  IndexOffset;
370   IndexOffset = (1 << ((Width < 0x80)? (Width - 1): (Width - 0x81)));
371   LibNbPciWrite (Address, Width, &Index, NbConfigPtr);
372   LibNbPciWrite (Address + IndexOffset , Width, Value, NbConfigPtr);
373 }
374
375 /*----------------------------------------------------------------------------------------*/
376 /**
377  * Read/Modify/Write  PCI Index/Data Address space
378  *
379  *
380  *
381  * @param[in] Address     Compressed PCIE address identical to PCI_ADDR.AddressValue
382  * @param[in] Index       Index Address.
383  * @param[in] Width       Access width of Index/Data register.
384  * @param[in] Mask       AND Mask.
385  * @param[in] Data       OR Mask.
386  * @param[in] NbConfigPtr Northbridge configuration structure pointer.
387  */
388 /*----------------------------------------------------------------------------------------*/
389
390 VOID
391 LibNbPciIndexRMW (
392   IN      UINT32        Address,
393   IN      UINT32        Index,
394   IN      ACCESS_WIDTH  Width,
395   IN      UINT32        Mask,
396   IN      UINT32        Data,
397   IN      AMD_NB_CONFIG *NbConfigPtr
398   )
399 {
400   UINT32  Value;
401   LibNbPciIndexRead (Address, Index, Width, &Value, NbConfigPtr);
402   Value = (Value & Mask) | Data;
403   LibNbPciIndexWrite (Address, Index, Width, &Value, NbConfigPtr);
404 }
405
406 /*----------------------------------------------------------------------------------------*/
407 /**
408  * Program table of indirect register.
409  *
410  *
411  *
412  * @param[in] Address     Compressed PCIE address identical to PCI_ADDR.AddressValue
413  * @param[in] Index       Index Address. Index address OR with INDIRECT_REG_ENTRY.Register
414  * @param[in] pTable      Pointer to indirect register table.
415  * @param[in] Length      Number of entry in indirect register table.
416  * @param[in] NbConfigPtr Northbridge configuration structure pointer.
417  */
418 /*----------------------------------------------------------------------------------------*/
419 VOID
420 LibNbIndirectTableInit (
421   IN      UINT32              Address,
422   IN      UINT32              Index,
423   IN      INDIRECT_REG_ENTRY  *pTable,
424   IN      UINTN               Length,
425   IN      AMD_NB_CONFIG       *NbConfigPtr
426   )
427 {
428   UINTN i;
429   for (i = 0; i < Length; i++) {
430     LibNbPciIndexRMW (Address, Index | pTable[i].Register , AccessS3SaveWidth32, pTable[i].Mask, pTable[i].Data, NbConfigPtr);
431   }
432 }
433
434 /*----------------------------------------------------------------------------------------*/
435 /*
436  * Find PCI capability pointer
437  *
438  *
439  *
440  *
441  *
442  */
443 /*----------------------------------------------------------------------------------------*/
444
445 UINT8
446 LibNbFindPciCapability (
447   IN      UINT32        Address,
448   IN      UINT8         CapabilityId,
449   IN      AMD_NB_CONFIG *NbConfigPtr
450   )
451 {
452   UINT8     CapabilityPtr;
453   UINT8     CurrentCapabilityId;
454   PCI_ADDR  Device;
455   Device.AddressValue = Address;
456   CapabilityPtr = 0x34;
457   if (!LibNbIsDevicePresent (Device, NbConfigPtr)) {
458     return  0;
459   }
460   while (CapabilityPtr != 0) {
461     LibNbPciRead (Address | CapabilityPtr, AccessWidth8 , &CapabilityPtr, NbConfigPtr);
462     if (CapabilityPtr) {
463       LibNbPciRead (Address | CapabilityPtr , AccessWidth8 , &CurrentCapabilityId, NbConfigPtr);
464       if (CurrentCapabilityId == CapabilityId) break;
465       CapabilityPtr++;
466     }
467   }
468   return  CapabilityPtr;
469 }
470 /*----------------------------------------------------------------------------------------*/
471 /*
472  * Find PCIe extended capability pointer
473  *
474  *
475  *
476  *
477  *
478  */
479 /*----------------------------------------------------------------------------------------*/
480
481 UINT16
482 LibNbFindPcieExtendedCapability (
483   IN      UINT32        Address,
484   IN      UINT16        ExtendedCapabilityId,
485   IN      AMD_NB_CONFIG *NbConfigPtr
486   )
487 {
488   UINT16  CapabilityPtr;
489   UINT32  ExtendedCapabilityIdBlock;
490   if (LibNbFindPciCapability (Address, 0x10, NbConfigPtr) != 0) {
491     CapabilityPtr = 0x100;
492     LibNbPciRead (Address | CapabilityPtr , AccessWidth32 , &ExtendedCapabilityIdBlock, NbConfigPtr);
493     if (ExtendedCapabilityIdBlock != 0 && (UINT16)ExtendedCapabilityIdBlock != 0xffff) {
494       do {
495         if ((UINT16)ExtendedCapabilityIdBlock == ExtendedCapabilityId) {
496           return  CapabilityPtr;
497         }
498         CapabilityPtr = (UINT16) ((ExtendedCapabilityIdBlock >> 20) & 0xfff);
499         LibNbPciRead (Address | CapabilityPtr , AccessWidth32 , &ExtendedCapabilityIdBlock, NbConfigPtr);
500       } while (CapabilityPtr !=  0);
501     }
502   }
503   return  0;
504 }
505
506
507 /*----------------------------------------------------------------------------------------*/
508 /**
509  * Read IO space
510  *
511  *
512  *
513  * @param[in] Address     IO Port address.
514  * @param[in] Width       Access width
515  * @param[in] Value       Pointer to save IO port value;
516  * @param[in] NbConfigPtr Northbridge configuration structure pointer.
517  */
518 /*----------------------------------------------------------------------------------------*/
519
520 VOID
521 LibNbIoRead (
522   IN       UINT16         Address,
523   IN       ACCESS_WIDTH   Width,
524      OUT   VOID           *Value,
525   IN       AMD_NB_CONFIG  *NbConfigPtr
526   )
527 {
528   LibAmdIoRead (Width, Address, Value, (AMD_CONFIG_PARAMS *)((NbConfigPtr == NULL)?NULL:GET_BLOCK_CONFIG_PTR (NbConfigPtr)));
529 }
530
531 /*----------------------------------------------------------------------------------------*/
532 /**
533  * Write IO space
534  *
535  *
536  *
537  * @param[in] Address     IO Port address.
538  * @param[in] Width       Access width
539  * @param[in] Value       Pointer to new IO port value
540  * @param[in] NbConfigPtr Northbridge configuration structure pointer.
541  */
542 VOID
543 LibNbIoWrite (
544   IN      UINT16         Address,
545   IN      ACCESS_WIDTH   Width,
546   IN      VOID           *Value,
547   IN      AMD_NB_CONFIG  *NbConfigPtr
548   )
549 {
550   LibAmdIoWrite (Width, Address, Value, (AMD_CONFIG_PARAMS *)((NbConfigPtr == NULL)?NULL:GET_BLOCK_CONFIG_PTR (NbConfigPtr)));
551 }
552
553
554 /*----------------------------------------------------------------------------------------*/
555 /**
556  * Read/Modify/Write IO space
557  *
558  *
559  *
560  * @param[in] Address     IO Port address.
561  * @param[in] Width       Access width
562  * @param[in] Mask       AND Mask
563  * @param[in] Data       OR Mask
564  * @param[in] NbConfigPtr Northbridge configuration structure pointer.
565  */
566 /*----------------------------------------------------------------------------------------*/
567
568 VOID
569 LibNbIoRMW (
570   IN      UINT16         Address,
571   IN      ACCESS_WIDTH   Width,
572   IN      UINT32         Mask,
573   IN      UINT32         Data,
574   IN      AMD_NB_CONFIG  *NbConfigPtr
575   )
576 {
577   UINT32  Value;
578   LibNbIoRead (Address, Width, &Value, NbConfigPtr);
579   Value = (Value & Mask) | Data;
580   LibNbIoWrite (Address, Width, &Value, NbConfigPtr);
581 }
582
583
584 /*----------------------------------------------------------------------------------------*/
585 /**
586  * Read CPU HT link Phy register
587  *
588  *
589  *
590  * @param[in] Node        Node device Address (0x18 - Node 0, 0x19 - Mode 1 etc.)
591  * @param[in] Link        HT Link ID (0 - Link 0, 1 - Link 1 etc.)
592  * @param[in] Register    Register address.
593  * @param[in] Value       Pointer to save register value
594  * @param[in] NbConfigPtr Northbridge configuration block pointer.
595  */
596 /*----------------------------------------------------------------------------------------*/
597
598 VOID
599 LibNbCpuHTLinkPhyRead (
600   IN       UINT8         Node,
601   IN       UINT8         Link,
602   IN       UINT16        Register,
603      OUT   UINT32        *Value,
604   IN       AMD_NB_CONFIG *NbConfigPtr
605   )
606 {
607   UINT32    Data;
608   PCI_ADDR  CpuPciAddress;
609   UINT8     LinkId;
610   LinkId = Link & 0xf;
611   CpuPciAddress.AddressValue = MAKE_SBDFO (0, 0, Node, 4, 0);
612   LibNbPciRMW (CpuPciAddress.AddressValue | (LinkId * 8 + 0x180), AccessWidth32, 0x0, Register | ((Register & 0xfe00)?BIT29:0), NbConfigPtr);
613   do {
614     LibNbPciRead (CpuPciAddress.AddressValue | (LinkId * 8 + 0x180), AccessWidth32, &Data, NbConfigPtr);
615   } while ((Data & BIT31) == 0);
616   LibNbPciRead (CpuPciAddress.AddressValue | (LinkId * 8 + 0x184), AccessWidth32, Value, NbConfigPtr);
617 }
618
619 /*----------------------------------------------------------------------------------------*/
620 /**
621  * Write CPU HT link Phy register
622  *
623  *
624  *
625  * @param[in] Node        Node device Address (0x18 - Node 0, 0x19 - Mode 1 etc.)
626  * @param[in] Link        HT Link ID (0 - Link 0, 1 - Link 1 etc.)
627  * @param[in] Register    Register address.
628  * @param[in] Value       Pointer to new register value
629  * @param[in] NbConfigPtr Northbridge configuration block pointer.
630  */
631 /*----------------------------------------------------------------------------------------*/
632
633 VOID
634 LibNbCpuHTLinkPhyWrite (
635   IN       UINT8         Node,
636   IN       UINT8         Link,
637   IN       UINT16        Register,
638   IN       UINT32        *Value,
639   IN       AMD_NB_CONFIG *NbConfigPtr
640   )
641 {
642   UINT32    Data;
643   PCI_ADDR  CpuPciAddress;
644   UINT8     LinkId;
645   LinkId = Link & 0xf;
646   CpuPciAddress.AddressValue = MAKE_SBDFO (0, 0, Node, 4, 0);
647   LibNbPciWrite (CpuPciAddress.AddressValue | (LinkId * 8 + 0x184), AccessWidth32, Value, NbConfigPtr);
648   LibNbPciRMW (CpuPciAddress.AddressValue | (LinkId * 8 + 0x180), AccessWidth32, 0x0, Register | BIT30 | ((Register & 0xfe00)?BIT29:0), NbConfigPtr);
649   do {
650     LibNbPciRead (CpuPciAddress.AddressValue | (LinkId * 8 + 0x180), AccessWidth32, &Data, NbConfigPtr);
651   } while ((Data & BIT31) == 0);
652 }
653
654
655 /*----------------------------------------------------------------------------------------*/
656 /**
657  *  Read/Modify/Write CPU HT link Phy register
658  *
659  *
660  *
661  * @param[in] Node        Node device Address (0x18 - Node 0, 0x19 - Mode 1 etc.)
662  * @param[in] Link        HT Link ID (0 - Link 0, 1 - Link 1 etc.)
663  * @param[in] Register    Register address.
664  * @param[in] Mask        AND Mask.
665  * @param[in] Data        OR Mask.
666  * @param[in] NbConfigPtr Northbridge configuration block pointer.
667  */
668 /*----------------------------------------------------------------------------------------*/
669 VOID
670 LibNbCpuHTLinkPhyRMW (
671   IN       UINT8           Node,
672   IN       UINT8           Link,
673   IN       UINT16          Register,
674   IN       UINT32          Mask,
675   IN       UINT32          Data,
676   IN       AMD_NB_CONFIG   *NbConfigPtr
677   )
678 {
679   UINT32  Value;
680   LibNbCpuHTLinkPhyRead (Node, Link, Register, &Value, NbConfigPtr);
681   Value = (Value & Mask) | Data;
682   LibNbCpuHTLinkPhyWrite (Node, Link, Register, &Value, NbConfigPtr);
683 }
684
685
686 /*----------------------------------------------------------------------------------------*/
687 /**
688  * Enable Clock Config space access.
689  *    Enable access to Clock Config Space at 0:0:1 PCI address.
690  *
691  *
692  * @param[in] pConfig Northbridge configuration block pointer.
693  */
694 /*----------------------------------------------------------------------------------------*/
695
696 VOID
697 LibNbEnableClkConfig (
698   IN      AMD_NB_CONFIG     *pConfig
699   )
700 {
701   LibNbPciRMW (NB_SBDFO | NB_PCI_REG4C, AccessS3SaveWidth8, (UINT32)~BIT0, BIT0, pConfig);
702 }
703
704 /*----------------------------------------------------------------------------------------*/
705 /**
706  * Disable Clock Config space access.
707  *    Disable access to Clock Config Space at 0:0:1 PCI address.
708  *
709  *
710  * @param[in] pConfig Northbridge configuration block pointer.
711  */
712 /*----------------------------------------------------------------------------------------*/
713
714 VOID
715 LibNbDisableClkConfig (
716   IN      AMD_NB_CONFIG     *pConfig
717   )
718 {
719   LibNbPciRMW (NB_SBDFO | NB_PCI_REG4C, AccessS3SaveWidth8, (UINT32)~BIT0, 0x0 , pConfig);
720 }
721
722
723 /*----------------------------------------------------------------------------------------*/
724 /**
725  * Check if PCI Device Present
726  *
727  *
728  *
729  * @param[in] Device      Device PCI address.
730  * @param[in] NbConfigPtr Northbridge configuration block pointer.
731  *
732  * @retval    TRUE        Device present.
733  * @retval    FALSE       Device not present.
734  */
735 /*----------------------------------------------------------------------------------------*/
736
737 BOOLEAN
738 LibNbIsDevicePresent (
739   IN      PCI_ADDR          Device,
740   IN      AMD_NB_CONFIG     *NbConfigPtr
741   )
742 {
743   UINT32 VendorId;
744   LibNbPciRead (Device.AddressValue, AccessWidth32, &VendorId, NbConfigPtr);
745   return (VendorId == 0xffffffff)?FALSE:TRUE;
746 }
747 /*----------------------------------------------------------------------------------------*/
748 /**
749  * Check if IOMMU enabled
750  *
751  *
752  *
753  * @param[in] NbConfigPtr Northbridge configuration block pointer.
754  *
755  * @retval    TRUE        IOMMU not enabled.
756  * @retval    FALSE       IOMMU not enabled.
757  */
758 /*----------------------------------------------------------------------------------------*/
759 BOOLEAN
760 LibNbIsIommuEnabled (
761   IN      AMD_NB_CONFIG     *NbConfigPtr
762   )
763 {
764   PCI_ADDR  IommuAddress;
765   IommuAddress.AddressValue = NbConfigPtr->NbPciAddress.AddressValue;
766   IommuAddress.Address.Function = 2;
767   if (LibNbIsDevicePresent (IommuAddress, NbConfigPtr)) {
768     UINT8 Value;
769     LibNbPciRead (IommuAddress.AddressValue | 0x44, AccessWidth8, &Value, NbConfigPtr);
770     if ((Value & BIT0) != 0) {
771       return  TRUE;
772     }
773   }
774   return FALSE;
775 }
776
777 /*----------------------------------------------------------------------------------------*/
778 /**
779  * Reverse bit in DWORD.
780  *    Reverse bits in bitfield inside DWORD.
781  *
782  *
783  * @param[in] Data        Value to reverse.
784  * @param[in] StartBit    Start bit.
785  * @param[in] StopBit     Stop bit.
786  * @retval                Reversed Value.
787  */
788 /*----------------------------------------------------------------------------------------*/
789
790 UINT32
791 LibNbBitReverse (
792   IN    UINT32    Data,
793   IN    UINT8     StartBit,
794   IN    UINT8     StopBit
795   )
796 {
797
798   UINT32 Bitr;
799   UINT32 Bitl;
800   UINT32 Distance;
801
802   while (StartBit < StopBit) {
803     Bitr = Data & (1 << StartBit );
804     Bitl = Data & (1 << StopBit );
805     Distance =    StopBit - StartBit;
806     Data = (Data & ((UINT32)~(Bitl | Bitr))) | (Bitr << Distance ) | (Bitl >> Distance);
807     StartBit++;
808     StopBit--;
809   }
810   return Data;
811 }
812 /*----------------------------------------------------------------------------------------*/
813 /**
814  * Read CPU family
815  *
816  *
817  *
818  * @retval  0xXX00000    CPU family.
819  *
820  */
821 UINT32
822 LibNbGetCpuFamily (
823   VOID
824   )
825 {
826   CPUID_DATA Cpuid;
827   CpuidRead (0x1, &Cpuid);
828   return Cpuid.EAX_Reg & 0xff00000;
829 }
830
831
832 /*----------------------------------------------------------------------------------------*/
833 /**
834  * Load Firmware block
835  *
836  *
837  *
838  * @param[in]   Address             Address to load firmware
839  * @param[in]   Size                Firmware block size
840  * @param[in]   FirmwareBlockPtr    Pointer to firmware block
841  * @param[in]   NbConfigPtr         Northbridge configuration block pointer.
842  *
843  */
844 VOID
845 LibNbLoadMcuFirmwareBlock (
846   IN      UINT16          Address,
847   IN      UINT16          Size,
848   IN      UINT32          *FirmwareBlockPtr,
849   IN      AMD_NB_CONFIG   *NbConfigPtr
850   )
851 {
852   UINT32    i;
853   PCI_ADDR  ClkPciAddress;
854   UINT32    Selector;
855
856   Selector =  (Address >=  0x200)?0x0000000:0x10000;
857   ClkPciAddress = NbConfigPtr->NbPciAddress;
858   ClkPciAddress.Address.Function = 1;
859   LibNbEnableClkConfig (NbConfigPtr);
860   for (i = 0; i < Size; i++) {
861     LibNbPciIndexWrite (ClkPciAddress.AddressValue | MC_CLK_INDEX, Selector | (Address + (i * 4)), AccessWidth32, &FirmwareBlockPtr[i], NbConfigPtr);
862   }
863   LibNbDisableClkConfig (NbConfigPtr);
864 }
865
866 /*----------------------------------------------------------------------------------------*/
867 /**
868  * Read SMU firmware ram
869  *
870  *
871  *
872  * @param[in]   Address             Address to read
873  * @param[in]   NbConfigPtr         Northbridge configuration block pointer.
874  *
875  */
876 UINT32
877 LibNbReadMcuRam (
878   IN      UINT16          Address,
879   IN      AMD_NB_CONFIG   *NbConfigPtr
880   )
881 {
882   UINT32    Value;
883   PCI_ADDR  ClkPciAddress;
884   UINT32    Selector;
885
886   Selector = (Address >=  0x200) ? 0x0000000 : 0x10000;
887   ClkPciAddress = NbConfigPtr->NbPciAddress;
888   ClkPciAddress.Address.Function = 1;
889   LibNbEnableClkConfig (NbConfigPtr);
890   LibNbPciIndexRead (ClkPciAddress.AddressValue | MC_CLK_INDEX, Selector | (Address), AccessWidth32, &Value, NbConfigPtr);
891   LibNbDisableClkConfig (NbConfigPtr);
892   return Value;
893 }
894
895 /*----------------------------------------------------------------------------------------*/
896 /**
897  * MCU Control
898  *
899  *
900  *
901  * @param[in]   Operation       Set/Reset MCU controller
902  * @param[in]   NbConfigPtr     Northbridge configuration block pointer.
903  */
904 VOID
905 LibNbMcuControl (
906   IN      NB_MCU_MODE     Operation,
907   IN      AMD_NB_CONFIG   *NbConfigPtr
908   )
909 {
910   PCI_ADDR  ClkPciAddress;
911   UINT32    Value;
912
913   Value =  (Operation == AssertReset)?0x00000ee1:0x00000ee2;
914   ClkPciAddress = NbConfigPtr->NbPciAddress;
915   ClkPciAddress.Address.Function = 1;
916   CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (NbConfigPtr), CIMX_NBPCIE_TRACE), "LibNbMcuControl Operation [0x%x]\n", Operation));
917   LibNbEnableClkConfig (NbConfigPtr);
918   LibNbPciIndexWrite (ClkPciAddress.AddressValue | MC_CLK_INDEX, 0x00030000, AccessWidth32, &Value, NbConfigPtr);
919   LibNbDisableClkConfig (NbConfigPtr);
920 }
921
922 /*----------------------------------------------------------------------------------------*/
923 /**
924  * Read/Modify/Write memory space
925  *
926  *
927  *
928  * @param[in] Address     Memory address.
929  * @param[in] Width       Access width
930  * @param[in] Mask        AND Mask
931  * @param[in] Data        OR Mask
932  * @param[in] NbConfigPtr Northbridge configuration structure pointer.
933  */
934 /*----------------------------------------------------------------------------------------*/
935
936 VOID
937 LibNbMemRMW (
938   IN      UINT64          Address,
939   IN      ACCESS_WIDTH    Width,
940   IN      UINT32          Mask,
941   IN      UINT32          Data,
942   IN      AMD_NB_CONFIG   *NbConfigPtr
943   )
944 {
945   UINT32  Value;
946   LibNbMemRead (Address, Width, &Value, NbConfigPtr);
947   Value = (Value & Mask) | Data;
948   LibNbMemWrite (Address, Width, &Value, NbConfigPtr);
949 }
950
951 /*----------------------------------------------------------------------------------------*/
952 /**
953  * Read memory space
954  *
955  *
956  *
957  * @param[in] Address     Memory address.
958  * @param[in] Width       Access width
959  * @param[in] Value       Pointer to memory to store value
960  * @param[in] NbConfigPtr Northbridge configuration structure pointer.
961  */
962 /*----------------------------------------------------------------------------------------*/
963
964 VOID
965 LibNbMemRead (
966   IN      UINT64          Address,
967   IN      ACCESS_WIDTH    Width,
968   IN      VOID            *Value,
969   IN      AMD_NB_CONFIG   *NbConfigPtr
970   )
971 {
972   LibAmdMemRead (Width, Address, Value, (AMD_CONFIG_PARAMS *)((NbConfigPtr == NULL)?NULL:GET_BLOCK_CONFIG_PTR (NbConfigPtr)));
973 }
974
975 /*----------------------------------------------------------------------------------------*/
976 /**
977  * Write memory space
978  *
979  *
980  *
981  * @param[in] Address     Memory address.
982  * @param[in] Width       Access width
983  * @param[in] Value       Pointer to memory to get value
984  * @param[in] NbConfigPtr Northbridge configuration structure pointer.
985  */
986 /*----------------------------------------------------------------------------------------*/
987
988 VOID
989 LibNbMemWrite (
990   IN       UINT64          Address,
991   IN       ACCESS_WIDTH    Width,
992      OUT   VOID            *Value,
993   IN       AMD_NB_CONFIG   *NbConfigPtr
994   )
995 {
996   LibAmdMemWrite (Width, Address, Value, (AMD_CONFIG_PARAMS *)((NbConfigPtr == NULL)?NULL:GET_BLOCK_CONFIG_PTR (NbConfigPtr)));
997 }
998
999 /*----------------------------------------------------------------------------------------*/
1000 /**
1001  * Scan Pci Bridge
1002  *
1003  *
1004  *
1005  * @param[in]   This            Pointer to PCI topology scan protocol
1006  * @param[in]   Bridge          Address of PCI to PCI bridge to scan.
1007  */
1008
1009 SCAN_STATUS
1010 LibNbScanPciBridgeBuses (
1011   IN      PCI_SCAN_PROTOCOL   *This,
1012   IN      PCI_ADDR            Bridge
1013   )
1014 {
1015   SCAN_STATUS Status;
1016   UINT8       CurrentBus;
1017   UINT8       MinBus;
1018   UINT8       MaxBus;
1019   PCI_ADDR    Device;
1020
1021   CIMX_ASSERT (This != NULL);
1022   if (This->ScanBus == NULL) {
1023     return  SCAN_FINISHED;
1024   }
1025   LibNbPciRead (Bridge.AddressValue | 0x19, AccessWidth8,  &MinBus, This->pConfig);
1026   LibNbPciRead (Bridge.AddressValue | 0x1A, AccessWidth8,  &MaxBus, This->pConfig);
1027   if (MinBus == 0 || MaxBus == 0) {
1028     return  SCAN_FINISHED;
1029   }
1030   CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (This->pConfig), CIMX_NBPCIE_TRACE), "    Scan bridge %d:%d:%d \n", Bridge.Address.Bus, Bridge.Address.Device, Bridge.Address.Function));
1031   for (CurrentBus = MinBus; CurrentBus <= MaxBus; CurrentBus++) {
1032     Device.AddressValue = MAKE_SBDFO (0, CurrentBus, 0, 0, 0);
1033     Status = This->ScanBus (This, Device);
1034   }
1035   return  SCAN_FINISHED;
1036 }
1037
1038
1039 /*----------------------------------------------------------------------------------------*/
1040 /**
1041  * Scan Pci Bus
1042  *
1043  *
1044  *
1045  * @param[in]   This            Pointer to PCI topology scan protocol
1046  * @param[in]   Device          Pci address device to start bus scan from
1047  */
1048 /*----------------------------------------------------------------------------------------*/
1049 SCAN_STATUS
1050 LibNbScanPciBus (
1051   IN      PCI_SCAN_PROTOCOL   *This,
1052   IN      PCI_ADDR            Device
1053   )
1054 {
1055   SCAN_STATUS Status;
1056   UINT32      CurrentDevice;
1057   CIMX_ASSERT (This != NULL);
1058   if (This->ScanDevice == NULL) {
1059     return  SCAN_FINISHED;
1060   }
1061   for (CurrentDevice = Device.Address.Device; CurrentDevice <= 0x1f; CurrentDevice++) {
1062     Device.Address.Device = CurrentDevice;
1063     if (LibNbIsDevicePresent (Device, This->pConfig)) {
1064       Status = This->ScanDevice (This, Device);
1065       if (Status == SCAN_STOP_BUS_ENUMERATION) {
1066         return Status;
1067       }
1068
1069     }
1070   }
1071   return  SCAN_FINISHED;
1072 }
1073
1074 /*----------------------------------------------------------------------------------------*/
1075 /**
1076  * Scan Pci Device
1077  *
1078  *
1079  *
1080  * @param[in]   This            Pointer to PCI topology scan protocol
1081  * @param[in]   Device          Pci address device to scan
1082  */
1083 /*----------------------------------------------------------------------------------------*/
1084
1085 SCAN_STATUS
1086 LibNbScanPciDevice (
1087   IN      PCI_SCAN_PROTOCOL   *This,
1088   IN      PCI_ADDR            Device
1089   )
1090 {
1091   SCAN_STATUS Status;
1092   UINT8       Header;
1093   UINT32      CurrentFunction;
1094   UINT32      MaxFunction;
1095   CIMX_ASSERT (This != NULL);
1096   if (This->ScanFunction == NULL) {
1097     return  SCAN_FINISHED;
1098   }
1099   LibNbPciRead (Device.AddressValue | 0x0E , AccessWidth8, &Header, This->pConfig);
1100   MaxFunction = (Header & 0x80)?7:0;
1101   for (CurrentFunction = Device.Address.Function; CurrentFunction <= MaxFunction; CurrentFunction++) {
1102     Device.Address.Function = CurrentFunction;
1103     if (LibNbIsDevicePresent (Device, This->pConfig)) {
1104       CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (This->pConfig), CIMX_NBPCIE_TRACE), "    Scan function %d:%d:%d \n", Device.Address.Bus, Device.Address.Device, Device.Address.Function));
1105       Status = This->ScanFunction (This, Device);
1106       if (Status == SCAN_STOP_DEVICE_ENUMERATION || Status == SCAN_STOP_BUS_ENUMERATION) {
1107         return Status;
1108       }
1109     }
1110   }
1111   return  SCAN_FINISHED;
1112 }
1113
1114 /*----------------------------------------------------------------------------------------*/
1115 /**
1116  * Set default Indexes
1117  *
1118  *
1119  * @param[in]   NbConfigPtr     Northbridge configuration block pointer.
1120  */
1121 /*----------------------------------------------------------------------------------------*/
1122
1123 VOID
1124 LibNbSetDefaultIndexes (
1125   IN      AMD_NB_CONFIG   *NbConfigPtr
1126   )
1127 {
1128   PCI_ADDR  PciAddress;
1129   PORT      PortId;
1130   LibNbPciRMW (NbConfigPtr->NbPciAddress.AddressValue | NB_HTIU_INDEX, AccessWidth32, 0x0, 0x0, NbConfigPtr);
1131   LibNbPciRMW (NbConfigPtr->NbPciAddress.AddressValue | NB_MISC_INDEX, AccessWidth32, 0x0, 0x0, NbConfigPtr);
1132   LibNbPciRMW (NbConfigPtr->NbPciAddress.AddressValue | NB_BIF_INDEX,  AccessWidth32, 0x0, SB_CORE, NbConfigPtr);
1133   PciAddress.AddressValue = NbConfigPtr->NbPciAddress.AddressValue;
1134   for (PortId = MIN_PORT_ID; PortId <= MAX_PORT_ID; PortId++) {
1135     PciAddress.Address.Device = PortId;
1136     LibNbPciRMW (PciAddress.AddressValue | NB_BIF_INDEX,  AccessWidth32, 0x0, 0x0, NbConfigPtr);
1137   }
1138 }