AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / CPU / Family / 0x15 / OR / cpuF15OrNbAfterReset.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * AMD Family_15 Orochi after warm reset sequence for NB P-states
6  *
7  * Performs the "NB COF and VID Transition Sequence After Warm Reset"
8  * as described in the BKDG.
9  *
10  * @xrefitem bom "File Content Label" "Release Content"
11  * @e project:      AGESA
12  * @e sub-project:  CPU/Family/0x15/OR
13  * @e \$Revision: 55600 $   @e \$Date: 2011-06-23 12:39:18 -0600 (Thu, 23 Jun 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  *                             M O D U L E S    U S E D
49  *----------------------------------------------------------------------------------------
50  */
51 #include "AGESA.h"
52 #include "amdlib.h"
53 #include "cpuF15PowerMgmt.h"
54 #include "cpuF15OrPowerMgmt.h"
55 #include "cpuRegisters.h"
56 #include "cpuApicUtilities.h"
57 #include "cpuFamilyTranslation.h"
58 #include "GeneralServices.h"
59 #include "cpuServices.h"
60 #include "OptionMultiSocket.h"
61 #include "cpuF15OrNbAfterReset.h"
62 #include "Filecode.h"
63 CODE_GROUP (G3_DXE)
64 RDATA_GROUP (G3_DXE)
65
66 #define FILECODE PROC_CPU_FAMILY_0X15_OR_CPUF15ORNBAFTERRESET_FILECODE
67
68 /*----------------------------------------------------------------------------------------
69  *                   D E F I N I T I O N S    A N D    M A C R O S
70  *----------------------------------------------------------------------------------------
71  */
72
73 /*----------------------------------------------------------------------------------------
74  *                  T Y P E D E F S     A N D     S T R U C T U R E S
75  *----------------------------------------------------------------------------------------
76  */
77
78 /*----------------------------------------------------------------------------------------
79  *           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
80  *----------------------------------------------------------------------------------------
81  */
82 VOID
83 STATIC
84 F15OrPmNbAfterResetOnCore (
85   IN       AMD_CONFIG_PARAMS *StdHeader
86   );
87
88 VOID
89 STATIC
90 TransitionToNbLow (
91   IN       PCI_ADDR           PciAddress,
92   IN       AMD_CONFIG_PARAMS  *StdHeader
93   );
94
95 VOID
96 STATIC
97 TransitionToNbHigh (
98   IN       PCI_ADDR           PciAddress,
99   IN       AMD_CONFIG_PARAMS  *StdHeader
100   );
101
102 VOID
103 STATIC
104 WaitForNbTransitionToComplete (
105   IN       PCI_ADDR           PciAddress,
106   IN       UINT32             PstateIndex,
107   IN       AMD_CONFIG_PARAMS  *StdHeader
108   );
109
110 /*----------------------------------------------------------------------------------------
111  *                          E X P O R T E D    F U N C T I O N S
112  *----------------------------------------------------------------------------------------
113  */
114 extern OPTION_MULTISOCKET_CONFIGURATION OptionMultiSocketConfiguration;
115
116 /*---------------------------------------------------------------------------------------*/
117 /**
118  * Family 15h Orochi core 0 entry point for performing the necessary steps after
119  * a warm reset has occurred.
120  *
121  * The steps are as follows:
122  *    1. Temp1 = D18F5x170[SwNbPstateLoDis].
123  *    2. Temp2 = D18F5x170[NbPstateDisOnP0].
124  *    3. Temp3 = D18F5x170[NbPstateThreshold].
125  *    4. If MSRC001_0070[NbPstate] = 1, go to step 9.
126  *    5. Write 0 to D18F5x170[SwNbPstateLoDis, NbPstateDisOnP0, NbPstateThreshold].
127  *    6. Wait for D18F5x174[CurNbPstate] = D18F5x170[NbPstateLo] and D18F5x174[CurNbFid,
128  *       CurNbDid] = [NbFid, NbDid] from D18F5x1[6C:60] indexed by D18F5x170[NbPstateLo].
129  *    7. Set D18F5x170[SwNbPstateLoDis] = 1.
130  *    8. Wait for D18F5x174[CurNbPstate] = D18F5x170[NbPstateHi] and D18F5x174[CurNbFid,
131  *       CurNbDid] = [NbFid, NbDid] from D18F5x1[6C:60] indexed by D18F5x170[NbPstateHi].
132  *       Go to step 13.
133  *    9. Set D18F5x170[SwNbPstateLoDis] = 1.
134  *   10. Wait for D18F5x174[CurNbPstate] = D18F5x170[NbPstateHi] and D18F5x174[CurNbFid,
135  *       CurNbDid] = [NbFid, NbDid] from D18F5x1[6C:60] indexed by D18F5x170[NbPstateHi].
136  *   11. Write 0 to D18F5x170[SwNbPstateLoDis, NbPstateDisOnP0, NbPstateThreshold].
137  *   12. Wait for D18F5x174[CurNbPstate] = D18F5x170[NbPstateLo] and D18F5x174[CurNbFid,
138  *       CurNbDid] = [NbFid, NbDid] from D18F5x1[6C:60] indexed by D18F5x170[NbPstateLo].
139  *   13. Set D18F5x170[SwNbPstateLoDis] = Temp1, D18F5x170[NbPstateDisOnP0] = Temp2, and
140  *       D18F5x170[NbPstateThreshold] = Temp3.
141  *
142  * @param[in]  FamilySpecificServices  The current Family Specific Services.
143  * @param[in]  CpuEarlyParamsPtr       Service parameters
144  * @param[in]  StdHeader               Config handle for library and services.
145  *
146  */
147 VOID
148 F15OrPmNbAfterReset (
149   IN       CPU_SPECIFIC_SERVICES *FamilySpecificServices,
150   IN       AMD_CPU_EARLY_PARAMS  *CpuEarlyParamsPtr,
151   IN       AMD_CONFIG_PARAMS     *StdHeader
152   )
153 {
154   UINT32    Socket;
155   UINT32    Module;
156   UINT32    Core;
157   UINT32    TaskedCore;
158   UINT32    Ignored;
159   AP_TASK   TaskPtr;
160   AGESA_STATUS IgnoredSts;
161
162   IdentifyCore (StdHeader, &Socket, &Module, &Core, &IgnoredSts);
163
164   ASSERT (Core == 0);
165
166   // Launch one core per node.
167   TaskPtr.FuncAddress.PfApTask = F15OrPmNbAfterResetOnCore;
168   TaskPtr.DataTransfer.DataSizeInDwords = 0;
169   TaskPtr.ExeFlags = WAIT_FOR_CORE;
170   for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) {
171     if (GetGivenModuleCoreRange (Socket, Module, &TaskedCore, &Ignored, StdHeader)) {
172       if (TaskedCore != 0) {
173         ApUtilRunCodeOnSocketCore ((UINT8) Socket, (UINT8) TaskedCore, &TaskPtr, StdHeader);
174       }
175     }
176   }
177   ApUtilTaskOnExecutingCore (&TaskPtr, StdHeader, (VOID *) CpuEarlyParamsPtr);
178 }
179
180
181 /*---------------------------------------------------------------------------------------
182  *                          L O C A L    F U N C T I O N S
183  *---------------------------------------------------------------------------------------
184  */
185
186 /*---------------------------------------------------------------------------------------*/
187 /**
188  * Support routine for F15OrPmNbAfterReset to perform MSR initialization on one
189  * core of each die in a family 15h socket.
190  *
191  * This function implements steps 1 - 13 on each core.
192  *
193  * @param[in]  StdHeader          Config handle for library and services.
194  *
195  */
196 VOID
197 STATIC
198 F15OrPmNbAfterResetOnCore (
199   IN       AMD_CONFIG_PARAMS *StdHeader
200   )
201 {
202   UINT32    NbPsCtrlOnEntry;
203   UINT32    NbPsCtrlOnExit;
204   UINT64    LocalMsrRegister;
205   PCI_ADDR  PciAddress;
206
207   // 1. Temp1 = D18F5x170[SwNbPstateLoDis].
208   // 2. Temp2 = D18F5x170[NbPstateDisOnP0].
209   // 3. Temp3 = D18F5x170[NbPstateThreshold].
210   OptionMultiSocketConfiguration.GetCurrPciAddr (&PciAddress, StdHeader);
211
212   PciAddress.Address.Function = FUNC_5;
213   PciAddress.Address.Register = NB_PSTATE_CTRL;
214   LibAmdPciRead (AccessWidth32, PciAddress, &NbPsCtrlOnEntry, StdHeader);
215
216   // Check if NB P-states were disabled, and if so, prevent any changes from occurring.
217   if (((NB_PSTATE_CTRL_REGISTER *) &NbPsCtrlOnEntry)->NbPstateMaxVal != 0) {
218     // 4. If MSRC001_0070[NbPstate] = 1, go to step 9
219     LibAmdMsrRead (MSR_COFVID_CTL, &LocalMsrRegister, StdHeader);
220     if (((COFVID_CTRL_MSR *) &LocalMsrRegister)->NbPstate == 0) {
221       // 5. Write 0 to D18F5x170[SwNbPstateLoDis, NbPstateDisOnP0, NbPstateThreshold].
222       // 6. Wait for D18F5x174[CurNbPstate] = D18F5x170[NbPstateLo] and D18F5x174[CurNbFid,
223       //    CurNbDid] = [NbFid, NbDid] from D18F5x1[6C:60] indexed by D18F5x170[NbPstateLo].
224       TransitionToNbLow (PciAddress, StdHeader);
225
226       // 7. Set D18F5x170[SwNbPstateLoDis] = 1.
227       // 8. Wait for D18F5x174[CurNbPstate] = D18F5x170[NbPstateHi] and D18F5x174[CurNbFid,
228       //    CurNbDid] = [NbFid, NbDid] from D18F5x1[6C:60] indexed by D18F5x170[NbPstateHi].
229       //    Go to step 13.
230       TransitionToNbHigh (PciAddress, StdHeader);
231     } else {
232       // 9. Set D18F5x170[SwNbPstateLoDis] = 1.
233       // 10. Wait for D18F5x174[CurNbPstate] = D18F5x170[NbPstateHi] and D18F5x174[CurNbFid,
234       //     CurNbDid] = [NbFid, NbDid] from D18F5x1[6C:60] indexed by D18F5x170[NbPstateHi].
235       TransitionToNbHigh (PciAddress, StdHeader);
236
237       // 11. Write 0 to D18F5x170[SwNbPstateLoDis, NbPstateDisOnP0, NbPstateThreshold].
238       // 12. Wait for D18F5x174[CurNbPstate] = D18F5x170[NbPstateLo] and D18F5x174[CurNbFid,
239       //     CurNbDid] = [NbFid, NbDid] from D18F5x1[6C:60] indexed by D18F5x170[NbPstateLo].
240       TransitionToNbLow (PciAddress, StdHeader);
241     }
242
243     // 13. Set D18F5x170[SwNbPstateLoDis] = Temp1, D18F5x170[NbPstateDisOnP0] = Temp2, and
244     //     D18F5x170[NbPstateThreshold] = Temp3.
245     LibAmdPciRead (AccessWidth32, PciAddress, &NbPsCtrlOnExit, StdHeader);
246     ((NB_PSTATE_CTRL_REGISTER *) &NbPsCtrlOnExit)->SwNbPstateLoDis = ((NB_PSTATE_CTRL_REGISTER *) &NbPsCtrlOnEntry)->SwNbPstateLoDis;
247     ((NB_PSTATE_CTRL_REGISTER *) &NbPsCtrlOnExit)->NbPstateDisOnP0 = ((NB_PSTATE_CTRL_REGISTER *) &NbPsCtrlOnEntry)->NbPstateDisOnP0;
248     ((NB_PSTATE_CTRL_REGISTER *) &NbPsCtrlOnExit)->NbPstateThreshold = ((NB_PSTATE_CTRL_REGISTER *) &NbPsCtrlOnEntry)->NbPstateThreshold;
249     LibAmdPciWrite (AccessWidth32, PciAddress, &NbPsCtrlOnExit, StdHeader);
250   }
251 }
252
253 /*---------------------------------------------------------------------------------------*/
254 /**
255  * Support routine for F15OrPmNbAfterResetOnCore to transition to the low NB P-state.
256  *
257  * This function implements steps 5, 6, 11, and 12 as needed.
258  *
259  * @param[in]  PciAddress         Segment, bus, device number of the node to transition.
260  * @param[in]  StdHeader          Config handle for library and services.
261  *
262  */
263 VOID
264 STATIC
265 TransitionToNbLow (
266   IN       PCI_ADDR           PciAddress,
267   IN       AMD_CONFIG_PARAMS  *StdHeader
268   )
269 {
270   UINT32   NbPsCtrl;
271
272   // 5/11. Write 0 to D18F5x170[SwNbPstateLoDis, NbPstateDisOnP0, NbPstateThreshold].
273   PciAddress.Address.Function = FUNC_5;
274   PciAddress.Address.Register = NB_PSTATE_CTRL;
275   LibAmdPciRead (AccessWidth32, PciAddress, &NbPsCtrl, StdHeader);
276   ((NB_PSTATE_CTRL_REGISTER *) &NbPsCtrl)->SwNbPstateLoDis = 0;
277   ((NB_PSTATE_CTRL_REGISTER *) &NbPsCtrl)->NbPstateDisOnP0 = 0;
278   ((NB_PSTATE_CTRL_REGISTER *) &NbPsCtrl)->NbPstateThreshold = 0;
279   LibAmdPciWrite (AccessWidth32, PciAddress, &NbPsCtrl, StdHeader);
280
281   // 6/12. Wait for D18F5x174[CurNbPstate] = D18F5x170[NbPstateLo] and D18F5x174[CurNbFid,
282   //       CurNbDid] = [NbFid, NbDid] from D18F5x1[6C:60] indexed by D18F5x170[NbPstateLo].
283   WaitForNbTransitionToComplete (PciAddress, ((NB_PSTATE_CTRL_REGISTER *) &NbPsCtrl)->NbPstateLo, StdHeader);
284 }
285
286 /*---------------------------------------------------------------------------------------*/
287 /**
288  * Support routine for F15OrPmNbAfterResetOnCore to transition to the high NB P-state.
289  *
290  * This function implements steps 7, 8, 9, and 10 as needed.
291  *
292  * @param[in]  PciAddress         Segment, bus, device number of the node to transition.
293  * @param[in]  StdHeader          Config handle for library and services.
294  *
295  */
296 VOID
297 STATIC
298 TransitionToNbHigh (
299   IN       PCI_ADDR           PciAddress,
300   IN       AMD_CONFIG_PARAMS  *StdHeader
301   )
302 {
303   UINT32   NbPsCtrl;
304
305   // 7/9. Set D18F5x170[SwNbPstateLoDis] = 1.
306   PciAddress.Address.Function = FUNC_5;
307   PciAddress.Address.Register = NB_PSTATE_CTRL;
308   LibAmdPciRead (AccessWidth32, PciAddress, &NbPsCtrl, StdHeader);
309   ((NB_PSTATE_CTRL_REGISTER *) &NbPsCtrl)->SwNbPstateLoDis = 1;
310   LibAmdPciWrite (AccessWidth32, PciAddress, &NbPsCtrl, StdHeader);
311
312   // 8/10. Wait for D18F5x174[CurNbPstate] = D18F5x170[NbPstateHi] and D18F5x174[CurNbFid,
313   //       CurNbDid] = [NbFid, NbDid] from D18F5x1[6C:60] indexed by D18F5x170[NbPstateHi].
314   WaitForNbTransitionToComplete (PciAddress, ((NB_PSTATE_CTRL_REGISTER *) &NbPsCtrl)->NbPstateHi, StdHeader);
315 }
316
317 /*---------------------------------------------------------------------------------------*/
318 /**
319  * Support routine for F15OrPmAfterResetCore to wait for NB FID and DID to
320  * match a specific P-state.
321  *
322  * This function implements steps 6, 8, 10, and 12 as needed.
323  *
324  * @param[in]  PciAddress         Segment, bus, device number of the node to transition.
325  * @param[in]  PstateIndex        P-state settings to match.
326  * @param[in]  StdHeader          Config handle for library and services.
327  *
328  */
329 VOID
330 STATIC
331 WaitForNbTransitionToComplete (
332   IN       PCI_ADDR           PciAddress,
333   IN       UINT32             PstateIndex,
334   IN       AMD_CONFIG_PARAMS  *StdHeader
335   )
336 {
337   UINT32   TargetNbPs;
338   UINT32   NbPsSts;
339
340   PciAddress.Address.Function = FUNC_5;
341   PciAddress.Address.Register = NB_PSTATE_0 + (PstateIndex << 2);
342   LibAmdPciRead (AccessWidth32, PciAddress, &TargetNbPs, StdHeader);
343   PciAddress.Address.Register = NB_PSTATE_STATUS;
344   do {
345     LibAmdPciRead (AccessWidth32, PciAddress, &NbPsSts, StdHeader);
346   } while ((((NB_PSTATE_STS_REGISTER *) &NbPsSts)->CurNbPstate != PstateIndex ||
347            (((NB_PSTATE_STS_REGISTER *) &NbPsSts)->CurNbFid != ((NB_PSTATE_REGISTER *) &TargetNbPs)->NbFid)) ||
348            (((NB_PSTATE_STS_REGISTER *) &NbPsSts)->CurNbDid != ((NB_PSTATE_REGISTER *) &TargetNbPs)->NbDid));
349 }