AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / HT / Features / htIds.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * AMD IDS HyperTransport Implementation.
6  *
7  * Contains AMD AGESA Integrated Debug HT related support.
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project:      AGESA
11  * @e sub-project:  HyperTransport
12  * @e \$Revision: 56279 $   @e \$Date: 2011-07-11 13:11:28 -0600 (Mon, 11 Jul 2011) $
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
45 #include "AGESA.h"
46 #include "amdlib.h"
47 #include "Ids.h"
48 #include "Topology.h"
49 #include "htFeat.h"
50 #include "IdsHt.h"
51 #include "htInterface.h"
52 #include "htInterfaceGeneral.h"
53 #include "htNb.h"
54 #include "heapManager.h"
55 #include "Filecode.h"
56 CODE_GROUP (G1_PEICC)
57 RDATA_GROUP (G2_PEI)
58 #define FILECODE PROC_HT_FEATURES_HTIDS_FILECODE
59
60
61 /*-------------------------------------------------------------------------------------*/
62 /**
63  * Apply an IDS port override to the desired HT link.
64  *
65  * The IDS port override allows absolute control of a link's frequency and width, such as
66  * would be used for board characterization and test.  The IDS backend code is responsible
67  * for handling the NV items and building them into a port override list.  Here we search
68  * that list for any overrides which apply, and update the data used by the HT feature code.
69  *
70  * @param[in]      IsSourcePort         Since we handle both ports on a match, only do that if TRUE.
71  * @param[in,out]  Port0                The PORTLIST item for the first endpoint of a link.
72  * @param[in,out]  Port1                The PORTLIST item for the second endpoint of a link.
73  * @param[in,out]  PortOverrideList     IN: A pointer to the port override list or NULL,
74  *                                      OUT: A pointer to the port override list.
75  * @param[in]      State                access to ht interface and nb support methods.
76  *
77  */
78 VOID
79 HtIdsGetPortOverride (
80   IN       BOOLEAN                    IsSourcePort,
81   IN OUT   PORT_DESCRIPTOR            *Port0,
82   IN OUT   PORT_DESCRIPTOR            *Port1,
83   IN OUT   HTIDS_PORT_OVERRIDE_LIST   *PortOverrideList,
84   IN       STATE_DATA                 *State
85   )
86 {
87   LOCATE_HEAP_PTR LocHeapParams;
88   UINT8 SocketA;
89   UINT8 SocketB;
90   UINT8 PackageLinkA;
91   UINT8 PackageLinkB;
92   HTIDS_PORT_OVERRIDE_LIST   p;
93
94   if (IsSourcePort) {
95     ASSERT (PortOverrideList != NULL);
96     // The caller can cache the override list by providing the pointer (to the heap buffer).
97     // If the pointer to the port override list is null, then check if it is on the heap,
98     // and update the caller's pointer so it is cached.
99     // If the buffer is not in heap, call the IDS backend to get the NV data (which is likely also
100     // in heap).
101     if (*PortOverrideList == NULL) {
102       // locate the table in heap
103       LocHeapParams.BufferHandle = IDS_HT_DATA_HANDLE;
104       if (HeapLocateBuffer (&LocHeapParams, State->ConfigHandle) == AGESA_SUCCESS) {
105         *PortOverrideList = (HTIDS_PORT_OVERRIDE_LIST)LocHeapParams.BufferPtr;
106       } else {
107         // Ask IDS backend code for the list
108         IDS_OPTION_HOOK (IDS_HT_CONTROL, PortOverrideList, State->ConfigHandle);
109       }
110     }
111     ASSERT (*PortOverrideList != NULL);
112
113     // Search the port override list to see if there is an override that applies to this link.
114     // The match criteria are if either endpoint of the current port list item matches
115     // port override.
116     p = *PortOverrideList;
117     SocketA = State->HtInterface->GetSocketFromMap (Port0->NodeID, State);
118     PackageLinkA = State->Nb->GetPackageLink (Port0->NodeID, Port0->Link, State->Nb);
119     SocketB = State->HtInterface->GetSocketFromMap (Port1->NodeID, State);
120     PackageLinkB = State->Nb->GetPackageLink (Port1->NodeID, Port1->Link, State->Nb);
121
122     while ((p != NULL) && (p->Socket != HT_LIST_TERMINAL)) {
123       if ((((p->Socket == SocketA) || (p->Socket == HT_LIST_MATCH_ANY)) &&
124                   ((p->Link == PackageLinkA) || ((p->Link == HT_LIST_MATCH_ANY) &&
125                   (!IsPackageLinkInternal (PackageLinkA))) || ((p->Link == HT_LIST_MATCH_INTERNAL_LINK) && (IsPackageLinkInternal (PackageLinkA))))) ||
126                 (((p->Socket == SocketB) || (p->Socket == HT_LIST_MATCH_ANY)) &&
127                   ((p->Link == PackageLinkB) || ((p->Link == HT_LIST_MATCH_ANY) &&
128                   (!IsPackageLinkInternal (PackageLinkA))) || ((p->Link == HT_LIST_MATCH_INTERNAL_LINK) && (IsPackageLinkInternal (PackageLinkB))))))
129           {
130         // Found a match, update width and frequency of both endpoints.
131         if (p->WidthIn != HT_LIST_TERMINAL) {
132           Port0->SelWidthIn = p->WidthIn;
133           Port1->SelWidthOut = p->WidthIn;
134         }
135         if (p->WidthOut != HT_LIST_TERMINAL) {
136           Port0->SelWidthOut = p->WidthOut;
137           Port1->SelWidthIn = p->WidthOut;
138         }
139         if (p->Frequency != HT_LIST_TERMINAL) {
140           Port0->SelFrequency = p->Frequency;
141           Port1->SelFrequency = p->Frequency;
142         }
143         break;
144       } else {
145         p++;
146       }
147     }
148   }
149 }
150