AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / HT / htInterfaceCoherent.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * External Interface implementation for coherent features.
6  *
7  * Contains routines for accessing the interface to the client BIOS,
8  * for support only required for coherent features.
9  *
10  * @xrefitem bom "File Content Label" "Release Content"
11  * @e project:      AGESA
12  * @e sub-project:  HyperTransport
13  * @e \$Revision: 56279 $   @e \$Date: 2011-07-11 13:11:28 -0600 (Mon, 11 Jul 2011) $
14  *
15  */
16 /*
17  *****************************************************************************
18  *
19  * Copyright (C) 2012 Advanced Micro Devices, Inc.
20  * All rights reserved.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions are met:
24  *     * Redistributions of source code must retain the above copyright
25  *       notice, this list of conditions and the following disclaimer.
26  *     * Redistributions in binary form must reproduce the above copyright
27  *       notice, this list of conditions and the following disclaimer in the
28  *       documentation and/or other materials provided with the distribution.
29  *     * Neither the name of Advanced Micro Devices, Inc. nor the names of
30  *       its contributors may be used to endorse or promote products derived
31  *       from this software without specific prior written permission.
32  *
33  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
34  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
35  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36  * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
37  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
39  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
40  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
41  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
42  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43  *
44  * ***************************************************************************
45  *
46  */
47
48 /*
49  *----------------------------------------------------------------------------
50  *                                MODULES USED
51  *
52  *----------------------------------------------------------------------------
53  */
54
55
56
57 #include "AGESA.h"
58 #include "amdlib.h"
59 #include "Ids.h"
60 #include "Topology.h"
61 #include "htFeat.h"
62 #include "htInterface.h"
63 #include "htInterfaceGeneral.h"
64 #include "htInterfaceCoherent.h"
65 #include "htNb.h"
66 #include "heapManager.h"
67 #include "Filecode.h"
68 CODE_GROUP (G1_PEICC)
69 RDATA_GROUP (G2_PEI)
70
71 #define FILECODE PROC_HT_HTINTERFACECOHERENT_FILECODE
72 /*----------------------------------------------------------------------------
73  *                          DEFINITIONS AND MACROS
74  *
75  *----------------------------------------------------------------------------
76  */
77
78 /*----------------------------------------------------------------------------
79  *                           TYPEDEFS AND STRUCTURES
80  *
81  *----------------------------------------------------------------------------
82  */
83 /*----------------------------------------------------------------------------
84  *                        PROTOTYPES OF LOCAL FUNCTIONS
85  *
86  *----------------------------------------------------------------------------
87  */
88 /*----------------------------------------------------------------------------
89  *                            EXPORTED FUNCTIONS
90  *
91  *----------------------------------------------------------------------------
92  */
93
94 /*----------------------------------------------------------------------------
95  *                              LOCAL FUNCTIONS
96  *
97  *----------------------------------------------------------------------------
98  */
99
100 /*----------------------------------------------------------------------------------------*/
101 /*----------------------------------------------------------------------------------------*/
102 /**
103  * Get limits for CPU to CPU Links.
104  *
105  * @HtInterfaceMethod{::F_GET_CPU_2_CPU_PCB_LIMITS}
106  *
107  * For each coherent connection this routine is called once.  Update the frequency
108  * and width if needed for this Link (usually based on board restriction).  This is
109  * used with CPU device capabilities and northbridge limits to compute the default
110  * settings.  The input width and frequency are valid, but do not necessarily reflect
111  * the minimum setting that will be chosen.
112  *
113  * @param[in]     NodeA One Node on which this Link is located
114  * @param[in]     LinkA The Link on this Node
115  * @param[in]     NodeB The other Node on which this Link is located
116  * @param[in]     LinkB The Link on that Node
117  * @param[in,out] ABLinkWidthLimit modify to change the Link Width In
118  * @param[in,out] BALinkWidthLimit modify to change the Link Width Out
119  * @param[in,out] PcbFreqCap modify to change the Link's frequency capability
120  * @param[in]     State the input data
121  *
122  */
123 VOID
124 GetCpu2CpuPcbLimits (
125   IN       UINT8        NodeA,
126   IN       UINT8        LinkA,
127   IN       UINT8        NodeB,
128   IN       UINT8        LinkB,
129   IN OUT   UINT8        *ABLinkWidthLimit,
130   IN OUT   UINT8        *BALinkWidthLimit,
131   IN OUT   UINT32       *PcbFreqCap,
132   IN       STATE_DATA   *State
133   )
134 {
135   CPU_TO_CPU_PCB_LIMITS *p;
136   UINT8 SocketA;
137   UINT8 SocketB;
138   UINT8 PackageLinkA;
139   UINT8 PackageLinkB;
140
141   ASSERT ((NodeA < MAX_NODES) && (NodeB < MAX_NODES));
142   ASSERT ((LinkA < State->Nb->MaxLinks) && (LinkB < State->Nb->MaxLinks));
143
144   SocketA = State->HtInterface->GetSocketFromMap (NodeA, State);
145   PackageLinkA = State->Nb->GetPackageLink (NodeA, LinkA, State->Nb);
146   SocketB = State->HtInterface->GetSocketFromMap (NodeB, State);
147   PackageLinkB = State->Nb->GetPackageLink (NodeB, LinkB, State->Nb);
148
149   if (State->HtBlock->CpuToCpuPcbLimitsList != NULL) {
150     p = State->HtBlock->CpuToCpuPcbLimitsList;
151
152     while (p->SocketA != HT_LIST_TERMINAL) {
153       if (((p->SocketA == SocketA) || (p->SocketA == HT_LIST_MATCH_ANY)) &&
154           ((p->LinkA == PackageLinkA) || ((p->LinkA == HT_LIST_MATCH_ANY) && (!IsPackageLinkInternal (PackageLinkA))) ||
155            ((p->LinkA == HT_LIST_MATCH_INTERNAL_LINK) && (IsPackageLinkInternal (PackageLinkA)))) &&
156           ((p->SocketB == SocketB) || (p->SocketB == HT_LIST_MATCH_ANY)) &&
157           ((p->LinkB == PackageLinkB) || ((p->LinkB == HT_LIST_MATCH_ANY) && (!IsPackageLinkInternal (PackageLinkB))) ||
158            ((p->LinkB == HT_LIST_MATCH_INTERNAL_LINK) && (IsPackageLinkInternal (PackageLinkB))))) {
159         // Found a match, update width and frequency
160         *ABLinkWidthLimit = p->ABLinkWidthLimit;
161         *BALinkWidthLimit = p->BALinkWidthLimit;
162         *PcbFreqCap = p->PcbFreqCap;
163         break;
164       } else {
165         p++;
166       }
167     }
168   }
169 }
170
171 /*----------------------------------------------------------------------------------------*/
172 /**
173  * Skip reganging of subLinks.
174  *
175  * @HtInterfaceMethod{::F_GET_SKIP_REGANG}
176  *
177  * This routine is called whenever two subLinks are both connected to the same CPUs.
178  * Normally, unganged sublinks between the same two CPUs are reganged.  Return true
179  * from this routine to leave the Links unganged.
180  *
181  * @param[in]     NodeA    One Node on which this Link is located
182  * @param[in]     LinkA    The Link on this Node
183  * @param[in]     NodeB    The other Node on which this Link is located
184  * @param[in]     LinkB    The Link on that Node
185  * @param[in]     State     the input data
186  *
187  * @retval        MATCHED      leave Link unganged
188  * @retval        POWERED_OFF  leave link unganged and power off the paired sublink
189  * @retval        UNMATCHED    regang Link automatically
190  */
191 FINAL_LINK_STATE
192 GetSkipRegang (
193   IN       UINT8        NodeA,
194   IN       UINT8        LinkA,
195   IN       UINT8        NodeB,
196   IN       UINT8        LinkB,
197   IN       STATE_DATA   *State
198   )
199 {
200   SKIP_REGANG *p;
201   FINAL_LINK_STATE Result;
202   UINT8 SocketA;
203   UINT8 SocketB;
204   UINT8 PackageLinkA;
205   UINT8 PackageLinkB;
206
207   ASSERT ((NodeA < MAX_NODES) && (NodeB < MAX_NODES));
208   ASSERT ((LinkA < State->Nb->MaxLinks) && (LinkB < State->Nb->MaxLinks));
209
210   Result = UNMATCHED;
211   SocketA = State->HtInterface->GetSocketFromMap (NodeA, State);
212   PackageLinkA = State->Nb->GetPackageLink (NodeA, LinkA, State->Nb);
213   SocketB = State->HtInterface->GetSocketFromMap (NodeB, State);
214   PackageLinkB = State->Nb->GetPackageLink (NodeB, LinkB, State->Nb);
215
216   if (State->HtBlock->SkipRegangList != NULL) {
217     p = State->HtBlock->SkipRegangList;
218
219     while (p->SocketA != HT_LIST_TERMINAL) {
220       if (((p->SocketA == SocketA) || (p->SocketA == HT_LIST_MATCH_ANY)) &&
221           ((p->LinkA == PackageLinkA) || ((p->LinkA == HT_LIST_MATCH_ANY) && (!IsPackageLinkInternal (PackageLinkA))) ||
222             ((p->LinkA == HT_LIST_MATCH_INTERNAL_LINK) && (IsPackageLinkInternal (PackageLinkA)))) &&
223           ((p->SocketB == SocketB) || (p->SocketB == HT_LIST_MATCH_ANY)) &&
224           ((p->LinkB == PackageLinkB) || ((p->LinkB == HT_LIST_MATCH_ANY) && (!IsPackageLinkInternal (PackageLinkB))) ||
225             ((p->LinkB == HT_LIST_MATCH_INTERNAL_LINK) && (IsPackageLinkInternal (PackageLinkB))))) {
226         // Found a match return final link state
227         Result = p->LinkState;
228         break;
229       } else {
230         p++;
231       }
232     }
233   }
234   return Result;
235 }
236
237 /*----------------------------------------------------------------------------------------*/
238 /**
239  * Get a new, empty Hop Count Table, to make one for the installed topology.
240  *
241  * @HtInterfaceMethod{::F_NEW_HOP_COUNT_TABLE}
242  *
243  * For SLIT, publish a matrix with the hop count, by allocating a buffer on heap with a
244  * known signature.
245  *
246  * @param[in,out]   State    Keep our buffer handle.
247  *
248  */
249 VOID
250 NewHopCountTable (
251   IN OUT   STATE_DATA     *State
252   )
253 {
254   ALLOCATE_HEAP_PARAMS AllocHeapParams;
255
256   AllocHeapParams.RequestedBufferSize = sizeof (HOP_COUNT_TABLE);
257   AllocHeapParams.BufferHandle = HOP_COUNT_TABLE_HANDLE;
258   AllocHeapParams.Persist = HEAP_SYSTEM_MEM;
259   if (HeapAllocateBuffer ( &AllocHeapParams, State->ConfigHandle) == AGESA_SUCCESS) {
260     State->HopCountTable = (HOP_COUNT_TABLE *)AllocHeapParams.BufferPtr;
261   } else {
262     State->HopCountTable = NULL;
263   }
264 }