AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / Recovery / HT / htInitReset.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * Recovery HT, a Hypertransport init for Boot Blocks.  For normal
6  * boots, run Recovery HT first in boot block, then run full HT init
7  * in the system BIOS.  Recovery HT moves the devices on the chain with
8  * the southbridge to their assigned device IDS, so that all their PCI
9  * Config space is accessible.
10  *
11  * @xrefitem bom "File Content Label" "Release Content"
12  * @e project:      AGESA
13  * @e sub-project:  Recovery HyperTransport
14  * @e \$Revision: 44324 $   @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
15  *
16  */
17 /*
18  *****************************************************************************
19  *
20  * Copyright (C) 2012 Advanced Micro Devices, Inc.
21  * All rights reserved.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions are met:
25  *     * Redistributions of source code must retain the above copyright
26  *       notice, this list of conditions and the following disclaimer.
27  *     * Redistributions in binary form must reproduce the above copyright
28  *       notice, this list of conditions and the following disclaimer in the
29  *       documentation and/or other materials provided with the distribution.
30  *     * Neither the name of Advanced Micro Devices, Inc. nor the names of
31  *       its contributors may be used to endorse or promote products derived
32  *       from this software without specific prior written permission.
33  *
34  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
35  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
36  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
37  * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
38  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
40  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
41  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
42  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
43  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44  *
45  * ***************************************************************************
46  *
47  */
48
49 /*
50  *----------------------------------------------------------------------------
51  *                                MODULES USED
52  *
53  *----------------------------------------------------------------------------
54  */
55
56
57
58 #include "AGESA.h"
59 #include "amdlib.h"
60 #include "Ids.h"
61 #include "AdvancedApi.h"
62 #include "GeneralServices.h"
63 #include "Filecode.h"
64 CODE_GROUP (G2_PEI)
65 RDATA_GROUP (G2_PEI)
66
67 #define FILECODE PROC_RECOVERY_HT_HTINITRESET_FILECODE
68 /*----------------------------------------------------------------------------
69  *                          DEFINITIONS AND MACROS
70  *
71  *----------------------------------------------------------------------------
72  */
73 #define MAX_NODES 1
74 #define MAX_LINKS 8
75
76 extern CONST AMD_HT_RESET_INTERFACE HtOptionResetDefaults;
77
78 /*----------------------------------------------------------------------------
79  *                           TYPEDEFS AND STRUCTURES
80  *
81  *----------------------------------------------------------------------------
82  */
83
84 /**
85  * Our global state data structure.
86  *
87  * Keep track of inputs and outputs, and keep any working state.
88  */
89 typedef struct {
90   AMD_HT_RESET_INTERFACE      *HtBlock;       ///< The interface
91   AGESA_STATUS                Status;         ///< Remember the highest severity status event
92   VOID                        *ConfigHandle;  ///< Config Pointer, opaque handle for passing to lib
93 } HTR_STATE_DATA;
94
95 /*----------------------------------------------------------------------------
96  *                        PROTOTYPES OF LOCAL FUNCTIONS
97  *
98  *----------------------------------------------------------------------------
99  */
100
101 /*----------------------------------------------------------------------------
102  *                            EXPORTED FUNCTIONS
103  *
104  *----------------------------------------------------------------------------
105  */
106
107 /*----------------------------------------------------------------------------
108  *                              LOCAL FUNCTIONS
109  *
110  *----------------------------------------------------------------------------
111  */
112
113 /***************************************************************************
114  ***               FAMILY/NORTHBRIDGE SPECIFIC FUNCTIONS                 ***
115  ***************************************************************************/
116
117 /*----------------------------------------------------------------------------------------*/
118 /**
119  * Enable Routing Tables.
120  *
121  * Turns routing tables on for a node zero.
122  *
123  * @param[in] State Our State
124  */
125
126 VOID
127 STATIC
128 HtrEnableRoutingTables (
129   IN HTR_STATE_DATA *State
130   )
131 {
132   PCI_ADDR Reg;
133   UINT32 Temp;
134   Temp = 0;
135   Reg.AddressValue = MAKE_SBDFO (0, 0, 24, 0, 0x6C);
136   LibAmdPciWriteBits (Reg, 0, 0, &Temp, State->ConfigHandle);
137 }
138
139 /***************************************************************************
140  ***                       Non-coherent init code                        ***
141  ***                             Algorithms                              ***
142  ***************************************************************************/
143 /*----------------------------------------------------------------------------------------*/
144 /**
145  * Process the SouthBridge Link.
146  *
147  * Process a non-coherent link, and setting the device ID for all devices found.
148  *
149  * @param[in] State Our State, Inputs
150  */
151 VOID
152 STATIC
153 HtrProcessLink (
154   IN HTR_STATE_DATA *State
155   )
156 {
157   UINT32 CurrentBUID;
158   UINT32 Temp;
159   UINT32 UnitIDcnt;
160   PCI_ADDR CurrentPtr;
161   UINT8 Depth;
162   BUID_SWAP_LIST *SwapPtr;
163   PCI_ADDR Link1ControlRegister;
164   BOOLEAN IsCaveDevice;
165
166   // No PCI init to run, everything has to be on Bus zero.  This makes fewer
167   // northbridge dependencies.
168   //
169   // Assign BUIDs so that config space for all devices is visible.
170   //
171   if (State->HtBlock->ManualBuidSwapList != NULL) {
172     // Manual non-coherent BUID assignment
173     // Assign BUID's per manual override
174     //
175     SwapPtr = &(State->HtBlock->ManualBuidSwapList->SwapList);
176     Depth = 0;
177     while (SwapPtr->Swaps[Depth].FromId != 0xFF) {
178       CurrentPtr.AddressValue = MAKE_SBDFO (0, 0, SwapPtr->Swaps[Depth].FromId, 0, 0);
179
180       do {
181         LibAmdPciFindNextCap (&CurrentPtr, State->ConfigHandle);
182         ASSERT (CurrentPtr.AddressValue != ILLEGAL_SBDFO);
183         LibAmdPciRead (AccessWidth32, CurrentPtr, &Temp, State->ConfigHandle);
184       } while ((Temp & (UINT32)0xE00000FF) != (UINT32)0x00000008); // HyperTransport Slave Capability
185
186       CurrentBUID = SwapPtr->Swaps[Depth].ToId;
187       // Set the device's BUID
188       LibAmdPciWriteBits (CurrentPtr, 20, 16, &CurrentBUID, State->ConfigHandle);
189       Depth++;
190     }
191   } else {
192     // Automatic non-coherent device detection
193     Depth = 0;
194     CurrentBUID = 1;
195     for (;;) {
196       CurrentPtr.AddressValue = MAKE_SBDFO (0, 0, 0, 0, 0);
197
198       LibAmdPciRead (AccessWidth32, CurrentPtr, &Temp, State->ConfigHandle);
199       if (Temp == (UINT32)0xFFFFFFFF) {
200         // No device found at currentPtr
201         break;
202       }
203
204       // HyperTransport Slave Capability
205       do {
206         LibAmdPciFindNextCap (&CurrentPtr, State->ConfigHandle);
207         if (CurrentPtr.AddressValue == ILLEGAL_SBDFO) {
208           // There is a device at currentPtr, but it isn't an HT device.
209           return;
210         }
211         LibAmdPciRead (AccessWidth32, CurrentPtr, &Temp, State->ConfigHandle);
212       } while ((Temp & (UINT32)0xE00000FF) != (UINT32)0x00000008); // HyperTransport Slave Capability
213
214       // Get the device's Unit ID Count.
215       LibAmdPciReadBits (CurrentPtr, 25, 21, &UnitIDcnt, State->ConfigHandle);
216       if ((UnitIDcnt + CurrentBUID) > 24) {
217         // An error handler for the case where we run out of BUID's on a chain
218         State->Status = AGESA_ERROR;
219         ASSERT (FALSE);
220         return;
221       }
222       // While we are still certain we are accessing this device, remember if it is a cave device.
223       // This is found by reading EOC from the Link 1 Control Register.
224       Link1ControlRegister = CurrentPtr;
225       Link1ControlRegister.Address.Register += 8;
226       LibAmdPciReadBits (Link1ControlRegister, 6, 6, &Temp, State->ConfigHandle);
227       IsCaveDevice = ((Temp == 0) ? FALSE : TRUE);
228
229       // Set the device's BUID
230       IDS_HDT_CONSOLE (HT_TRACE, "Device found at depth=%d.\n", Depth);
231       LibAmdPciWriteBits (CurrentPtr, 20, 16, &CurrentBUID, State->ConfigHandle);
232
233       CurrentPtr.Address.Device = CurrentBUID;
234       // Get the device's BUID
235       LibAmdPciReadBits (CurrentPtr, 20, 16, &Temp, State->ConfigHandle);
236       if (Temp != CurrentBUID) {
237         if ((Depth == 0) && IsCaveDevice) {
238           // If the chain only consists of a single cave device, that device may have retained zero
239           // for it's BUID.
240           CurrentPtr.Address.Device = 0;
241           LibAmdPciReadBits (CurrentPtr, 20, 16, &Temp, State->ConfigHandle);
242           if (Temp == 0) {
243             // Per HyperTransport specification, devices not accepting BUID reassignment hardwire BUID to zero.
244             Depth++;
245             // Success!
246             IDS_HDT_CONSOLE (HT_TRACE, "Compliant Cave at BUID=0.\n");
247             break;
248           } else if (Temp == CurrentBUID) {
249             // and then, there are the other kind of devices ....
250             // Restore the writable BUID field (which contains the value we just wrote) to zero.
251             Temp = 0;
252             LibAmdPciWriteBits (CurrentPtr, 20, 16, &Temp, State->ConfigHandle);
253             Depth++;
254             // Success!
255             IDS_HDT_CONSOLE (HT_TRACE, "Cave left at BUID=0.\n");
256             break;
257           }
258         }
259         // An error handler for this critical error
260         State->Status = AGESA_ERROR;
261         ASSERT (FALSE);
262         return;
263       }
264
265       IDS_HDT_CONSOLE (HT_TRACE, "Compliant Device assigned at BUID=%d.\n", CurrentBUID);
266       Depth++;
267       CurrentBUID += UnitIDcnt;
268     }
269     // Provide information on automatic device results
270     State->HtBlock->Depth = Depth;
271   }
272 }
273
274 /***************************************************************************
275  ***                           HT Reset Initialize                    ***
276  ***************************************************************************/
277
278 /**
279  * A constructor for the HyperTransport input structure.
280  *
281  * Sets inputs to valid, basic level, defaults.
282  *
283  * @param[in]     StdHeader             Config handle
284  * @param[in,out] AmdHtResetInterface   HT Interface structure to initialize.
285  *
286  * @retval AGESA_SUCCESS      Constructors are not allowed to fail
287 */
288 AGESA_STATUS
289 AmdHtResetConstructor (
290   IN       AMD_CONFIG_PARAMS         *StdHeader,
291   IN       AMD_HT_RESET_INTERFACE    *AmdHtResetInterface
292   )
293 {
294   AmdHtResetInterface->ManualBuidSwapList = HtOptionResetDefaults.ManualBuidSwapList;
295   return AGESA_SUCCESS;
296 }
297
298
299 /*----------------------------------------------------------------------------------------*/
300 /**
301  * Initialize HT for Reset, Boot Blocks.
302  *
303  * This is the top level external interface for Hypertransport Reset Initialization.
304  * Create our initial internal state and initialize the non-coherent chain to the
305  * southbridge.  This interface must be executed by both normal and recovery boot paths.
306  *
307  * @param[in]  StdHeader                 Interface structure
308  * @param[in]  AmdHtResetInterface       our interface and inputs
309  *
310  * @retval AGESA_SUCCESS Successful init
311  * @retval AGESA_ERROR   Device Error, BUID max exceed error.
312  *
313  */
314 AGESA_STATUS
315 AmdHtInitReset (
316   IN       AMD_CONFIG_PARAMS        *StdHeader,
317   IN       AMD_HT_RESET_INTERFACE   *AmdHtResetInterface
318   )
319 {
320   HTR_STATE_DATA State;
321   AGESA_STATUS IgnoredStatus;
322
323   State.Status = AGESA_SUCCESS;
324   if (IsBsp (StdHeader, &IgnoredStatus)) {
325     State.ConfigHandle = (AMD_CONFIG_PARAMS *)StdHeader;
326     State.HtBlock = AmdHtResetInterface;
327     HtrEnableRoutingTables (&State);
328
329     HtrProcessLink (&State);
330   }
331   return State.Status;
332 }