AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / HT / Features / htFeatGanging.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * Routines for re-ganging Links.
6  *
7  * Implement the reganging feature.
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 *****************************************************************************
17 *
18 * Copyright (C) 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.
42 *
43 * ***************************************************************************
44 *
45 */
46
47 /*
48  *----------------------------------------------------------------------------
49  *                                MODULES USED
50  *
51  *----------------------------------------------------------------------------
52  */
53
54
55 #include "AGESA.h"
56 #include "amdlib.h"
57 #include "Ids.h"
58 #include "Topology.h"
59 #include "htFeat.h"
60 #include "htInterface.h"
61 #include "htNb.h"
62 #include "htFeatGanging.h"
63 #include "Filecode.h"
64 CODE_GROUP (G1_PEICC)
65 RDATA_GROUP (G2_PEI)
66
67 #define FILECODE PROC_HT_FEATURES_HTFEATGANGING_FILECODE
68 /*----------------------------------------------------------------------------
69  *                          DEFINITIONS AND MACROS
70  *
71  *----------------------------------------------------------------------------
72  */
73
74 /*----------------------------------------------------------------------------
75  *                           TYPEDEFS AND STRUCTURES
76  *
77  *----------------------------------------------------------------------------
78  */
79
80 /*----------------------------------------------------------------------------
81  *                        PROTOTYPES OF LOCAL FUNCTIONS
82  *
83  *----------------------------------------------------------------------------
84  */
85
86 /*----------------------------------------------------------------------------
87  *                            EXPORTED FUNCTIONS
88  *
89  *----------------------------------------------------------------------------
90  */
91
92 /*----------------------------------------------------------------------------
93  *                              LOCAL FUNCTIONS
94  *
95  *----------------------------------------------------------------------------
96  */
97
98 /***************************************************************************
99  ***                            Link Optimization                        ***
100  ***************************************************************************/
101
102 /*----------------------------------------------------------------------------------------*/
103 /**
104  * Test the subLinks of a Link to see if they qualify to be reganged.
105  *
106  * @HtFeatMethod{::F_REGANG_LINKS}
107  *
108  * If they do, update the port list data to indicate that this should be done.
109  * @note  no actual hardware state is changed in this routine.
110  *
111  * @param[in,out] State          Our global state
112  */
113 VOID
114 RegangLinks (
115   IN OUT   STATE_DATA *State
116   )
117 {
118   FINAL_LINK_STATE FinalLinkState;
119   UINT8 i;
120   UINT8 j;
121   for (i = 0; i < (State->TotalLinks * 2); i += 2) {
122     // Data validation
123     ASSERT ((*State->PortList)[i].Type < 2 && (*State->PortList)[i].Link < State->Nb->MaxLinks);
124     ASSERT ((*State->PortList)[i + 1].Type < 2 && (*State->PortList)[i + 1].Link < State->Nb->MaxLinks);
125
126     // Regang is false unless we pass all conditions below
127     (*State->PortList)[i].SelRegang = FALSE;
128     (*State->PortList)[i + 1].SelRegang = FALSE;
129
130     // Only process cpu to cpu Links
131     if ( ((*State->PortList)[i].Type != PORTLIST_TYPE_CPU) ||
132          ((*State->PortList)[i + 1].Type != PORTLIST_TYPE_CPU)) {
133       continue;
134     }
135
136     for (j = i + 2; j < State->TotalLinks*2; j += 2) {
137       // Only process cpu to cpu Links
138       if ( ((*State->PortList)[j].Type != PORTLIST_TYPE_CPU) ||
139            ((*State->PortList)[j + 1].Type != PORTLIST_TYPE_CPU) ) {
140         continue;
141       }
142
143       // Links must be from the same source
144       if ((*State->PortList)[i].NodeID != (*State->PortList)[j].NodeID) {
145         continue;
146       }
147
148       // Link must be to the same target
149       if ((*State->PortList)[i + 1].NodeID != (*State->PortList)[j + 1].NodeID) {
150         continue;
151       }
152
153       // Ensure same source base port
154       if (((*State->PortList)[i].Link & 3) != ((*State->PortList)[j].Link & 3)) {
155         continue;
156       }
157
158       // Ensure same destination base port
159       if (((*State->PortList)[i + 1].Link & 3) != ((*State->PortList)[j + 1].Link & 3)) {
160         continue;
161       }
162
163       // Ensure subLink0 routes to subLink0
164       if (((*State->PortList)[i].Link & 4) != ((*State->PortList)[i + 1].Link & 4)) {
165         continue;
166       }
167
168       // (therefore subLink1 routes to subLink1)
169       ASSERT (((*State->PortList)[j].Link & 4) == ((*State->PortList)[j + 1].Link & 4));
170
171       FinalLinkState = State->HtInterface->GetSkipRegang ((*State->PortList)[i].NodeID,
172                                          (*State->PortList)[i].Link & 0x03,
173                                          (*State->PortList)[i + 1].NodeID,
174                                          (*State->PortList)[i + 1].Link & 0x03,
175                                          State);
176       if (FinalLinkState == MATCHED) {
177         continue;
178       } else if (FinalLinkState == POWERED_OFF) {
179         // StopLink will be done on the sublink 1, thus OR in 4 to the link to ensure it.
180         State->Nb->StopLink ((*State->PortList)[i].NodeID, ((*State->PortList)[i].Link | 4), State, State->Nb);
181         State->Nb->StopLink ((*State->PortList)[i + 1].NodeID, ((*State->PortList)[i + 1].Link | 4), State, State->Nb);
182       }
183
184       //
185       // Create a ganged portlist entry for the two regang-able subLinks.
186       //
187       // All info will be that of subLink zero.
188       // (If Link discovery order was other than ascending, fix the .Pointer field too.)
189       //
190       //
191       if (((*State->PortList)[i].Link & 4) != 0) {
192         (*State->PortList)[i].Pointer = (*State->PortList)[j].Pointer;
193         (*State->PortList)[i + 1].Pointer = (*State->PortList)[j + 1].Pointer;
194       }
195       (*State->PortList)[i].Link &= 0x03;                       // Force to point to subLink0
196       (*State->PortList)[i + 1].Link &= 0x03;
197       // If powered off, sublink 1 is removed but the link is still 8 bits.
198       if (FinalLinkState != POWERED_OFF) {
199         (*State->PortList)[i].SelRegang = TRUE;                   // Enable Link reganging
200         (*State->PortList)[i + 1].SelRegang = TRUE;
201         (*State->PortList)[i].PrvWidthOutCap = HT_WIDTH_16_BITS;
202         (*State->PortList)[i + 1].PrvWidthOutCap = HT_WIDTH_16_BITS;
203         (*State->PortList)[i].PrvWidthInCap = HT_WIDTH_16_BITS;
204         (*State->PortList)[i + 1].PrvWidthInCap = HT_WIDTH_16_BITS;
205       }
206
207       // Delete PortList[j, j + 1], slow but easy to debug implementation
208       State->TotalLinks--;
209       LibAmdMemCopy (&((*State->PortList)[j]),
210                      &((*State->PortList)[j + 2]),
211                      sizeof (PORT_DESCRIPTOR)*(State->TotalLinks* 2 - j),
212                      State->ConfigHandle);
213       LibAmdMemFill (&((*State->PortList)[State->TotalLinks * 2]), INVALID_LINK, (sizeof (PORT_DESCRIPTOR) * 2), State->ConfigHandle);
214
215       break; // Exit loop, advance to PortList[i + 2]
216     }
217   }
218 }