Frank Vibrans | 2b4c831 | 2011-02-14 18:30:54 +0000 | [diff] [blame] | 1 | /* $NoKeywords:$ */ |
| 2 | /** |
| 3 | * @file |
| 4 | * |
| 5 | * AMD Family_14 Power Plane Initialization |
| 6 | * |
| 7 | * Performs the "BIOS Requirements for Power Plane Initialization" as described |
| 8 | * in the BKDG. |
| 9 | * |
| 10 | * @xrefitem bom "File Content Label" "Release Content" |
| 11 | * @e project: AGESA |
| 12 | * @e sub-project: CPU/F14 |
| 13 | * @e \$Revision: 39275 $ @e \$Date: 2010-10-09 08:22:05 +0800 (Sat, 09 Oct 2010) $ |
| 14 | * |
| 15 | */ |
| 16 | /* |
| 17 | ***************************************************************************** |
| 18 | * |
| 19 | * Copyright (c) 2011, Advanced Micro Devices, Inc. |
| 20 | * All rights reserved. |
Edward O'Callaghan | 1542a6f | 2014-07-06 19:24:06 +1000 | [diff] [blame] | 21 | * |
Frank Vibrans | 2b4c831 | 2011-02-14 18:30:54 +0000 | [diff] [blame] | 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. |
Edward O'Callaghan | 1542a6f | 2014-07-06 19:24:06 +1000 | [diff] [blame] | 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 |
Frank Vibrans | 2b4c831 | 2011-02-14 18:30:54 +0000 | [diff] [blame] | 31 | * from this software without specific prior written permission. |
Edward O'Callaghan | 1542a6f | 2014-07-06 19:24:06 +1000 | [diff] [blame] | 32 | * |
Frank Vibrans | 2b4c831 | 2011-02-14 18:30:54 +0000 | [diff] [blame] | 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. |
Edward O'Callaghan | 1542a6f | 2014-07-06 19:24:06 +1000 | [diff] [blame] | 43 | * |
Frank Vibrans | 2b4c831 | 2011-02-14 18:30:54 +0000 | [diff] [blame] | 44 | * *************************************************************************** |
| 45 | * |
| 46 | */ |
| 47 | |
| 48 | /*---------------------------------------------------------------------------------------- |
| 49 | * M O D U L E S U S E D |
| 50 | *---------------------------------------------------------------------------------------- |
| 51 | */ |
| 52 | #include "AGESA.h" |
| 53 | #include "amdlib.h" |
| 54 | #include "Ids.h" |
| 55 | #include "cpuCacheInit.h" |
| 56 | #include "cpuRegisters.h" |
| 57 | #include "cpuFamilyTranslation.h" |
| 58 | #include "cpuServices.h" |
| 59 | #include "cpuF14PowerMgmt.h" |
efdesign98 | 84cbce2 | 2011-08-04 12:09:17 -0600 | [diff] [blame] | 60 | #include "cpuF14PowerPlane.h" |
Frank Vibrans | 2b4c831 | 2011-02-14 18:30:54 +0000 | [diff] [blame] | 61 | #include "OptionFamily14hEarlySample.h" |
| 62 | #include "NbSmuLib.h" |
| 63 | #include "GnbRegistersON.h" |
| 64 | #include "Filecode.h" |
| 65 | #define FILECODE PROC_CPU_FAMILY_0X14_CPUF14POWERPLANE_FILECODE |
| 66 | |
| 67 | /*---------------------------------------------------------------------------------------- |
| 68 | * D E F I N I T I O N S A N D M A C R O S |
| 69 | *---------------------------------------------------------------------------------------- |
| 70 | */ |
| 71 | extern F14_ES_CORE_SUPPORT F14EarlySampleCoreSupport; |
| 72 | |
| 73 | // Register encodings for D18F3xD8[VSRampSlamTime] |
| 74 | STATIC CONST UINT32 ROMDATA F14VSRampSlamWaitTimes[8] = |
| 75 | { |
| 76 | 625, // 000b: 6.25us |
| 77 | 500, // 001b: 5.00us |
| 78 | 417, // 010b: 4.17us |
| 79 | 313, // 011b: 3.13us |
| 80 | 250, // 100b: 2.50us |
| 81 | 167, // 101b: 1.67us |
| 82 | 125, // 110b: 1.25us |
| 83 | 100 // 111b: 1.00us |
| 84 | }; |
| 85 | |
| 86 | /*---------------------------------------------------------------------------------------- |
| 87 | * T Y P E D E F S A N D S T R U C T U R E S |
| 88 | *---------------------------------------------------------------------------------------- |
| 89 | */ |
| 90 | |
| 91 | /*---------------------------------------------------------------------------------------- |
| 92 | * 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 |
| 93 | *---------------------------------------------------------------------------------------- |
| 94 | */ |
| 95 | VOID |
| 96 | STATIC |
| 97 | F14PmVrmLowPowerModeEnable ( |
| 98 | IN CPU_SPECIFIC_SERVICES *FamilySpecificServices, |
| 99 | IN AMD_CPU_EARLY_PARAMS *CpuEarlyParams, |
| 100 | IN AMD_CONFIG_PARAMS *StdHeader |
| 101 | ); |
| 102 | |
| 103 | |
| 104 | /*---------------------------------------------------------------------------------------- |
| 105 | * E X P O R T E D F U N C T I O N S |
| 106 | *---------------------------------------------------------------------------------------- |
| 107 | */ |
| 108 | |
| 109 | /*---------------------------------------------------------------------------------------*/ |
| 110 | /** |
| 111 | * Family 14h core 0 entry point for performing power plane initialization. |
| 112 | * |
| 113 | * The steps are as follows: |
| 114 | * 1. BIOS must initialize D18F3xD8[VSRampSlamTime]. |
| 115 | * 2. BIOS must configure D18F3xA0[PsiVidEn & PsiVid] and |
| 116 | * D18F3x128[NbPsiVidEn & NbPsiVid]. |
| 117 | * 3. BIOS must program D18F3xDC[NbPs0Vid] = FCRxFE00_6000[NbPs0Vid] - 1. |
| 118 | * BIOS must program D18F3xDC[NbPs0Vid] = FCRxFE00_6000[NbPs0Vid]. |
| 119 | * |
| 120 | * @param[in] FamilySpecificServices The current Family Specific Services. |
| 121 | * @param[in] CpuEarlyParams Service parameters |
| 122 | * @param[in] StdHeader Config handle for library and services. |
| 123 | * |
| 124 | */ |
| 125 | VOID |
| 126 | F14PmPwrPlaneInit ( |
| 127 | IN CPU_SPECIFIC_SERVICES *FamilySpecificServices, |
| 128 | IN AMD_CPU_EARLY_PARAMS *CpuEarlyParams, |
| 129 | IN AMD_CONFIG_PARAMS *StdHeader |
| 130 | ) |
| 131 | { |
| 132 | UINT32 SystemSlewRate; |
efdesign98 | 84cbce2 | 2011-08-04 12:09:17 -0600 | [diff] [blame] | 133 | UINT32 PciReg; |
Frank Vibrans | 2b4c831 | 2011-02-14 18:30:54 +0000 | [diff] [blame] | 134 | UINT32 WaitTime; |
| 135 | UINT32 VSRampSlamTime; |
| 136 | PCI_ADDR PciAddress; |
| 137 | FCRxFE00_6000_STRUCT FCRxFE00_6000; |
| 138 | |
| 139 | // Step 1 - Configure D18F3xD8[VSRampSlamTime] based on platform requirements. |
| 140 | // Voltage Ramp Time = maximum time to change voltage by 12.5mV rounded to the next higher encoding. |
| 141 | SystemSlewRate = (CpuEarlyParams->PlatformConfig.VrmProperties[CoreVrm].SlewRate <= |
| 142 | CpuEarlyParams->PlatformConfig.VrmProperties[NbVrm].SlewRate) ? |
| 143 | CpuEarlyParams->PlatformConfig.VrmProperties[CoreVrm].SlewRate : |
| 144 | CpuEarlyParams->PlatformConfig.VrmProperties[NbVrm].SlewRate; |
| 145 | |
| 146 | ASSERT (SystemSlewRate != 0); |
| 147 | |
| 148 | // First, calculate the time it takes to change 12.5mV using the VRM slew rate. |
| 149 | WaitTime = (12500 * 100) / SystemSlewRate; |
| 150 | if (((12500 * 100) % SystemSlewRate) != 0) { |
| 151 | WaitTime++; |
| 152 | } |
| 153 | |
| 154 | // Next, round it to the appropriate encoded value. We will start from encoding 111b which corresponds |
| 155 | // to the fastest slew rate, and work our way down to 000b, which represents the slowest an acceptable |
| 156 | // VRM can be. |
Patrick Georgi | 6b688f5 | 2021-02-12 13:49:11 +0100 | [diff] [blame] | 157 | for (VSRampSlamTime = (ARRAY_SIZE(F14VSRampSlamWaitTimes)- 1); VSRampSlamTime > 0; VSRampSlamTime--) { |
Frank Vibrans | 2b4c831 | 2011-02-14 18:30:54 +0000 | [diff] [blame] | 158 | if (WaitTime <= F14VSRampSlamWaitTimes[VSRampSlamTime]) { |
| 159 | break; |
| 160 | } |
| 161 | } |
| 162 | |
| 163 | if (WaitTime > F14VSRampSlamWaitTimes[0]) { |
| 164 | // The VRMs on this motherboard are too slow for this CPU. |
| 165 | IDS_ERROR_TRAP; |
| 166 | } |
| 167 | |
| 168 | // Lastly, program D18F3xD8[VSRampSlamTime] with the appropriate encoded value. |
| 169 | PciAddress.AddressValue = CPTC1_PCI_ADDR; |
efdesign98 | 84cbce2 | 2011-08-04 12:09:17 -0600 | [diff] [blame] | 170 | LibAmdPciRead (AccessWidth32, PciAddress, &PciReg, StdHeader); |
| 171 | ((CLK_PWR_TIMING_CTRL1_REGISTER *) &PciReg)->VSRampSlamTime = VSRampSlamTime; |
| 172 | LibAmdPciWrite (AccessWidth32, PciAddress, &PciReg, StdHeader); |
Frank Vibrans | 2b4c831 | 2011-02-14 18:30:54 +0000 | [diff] [blame] | 173 | |
| 174 | // Step 2 - Configure D18F3xA0[PsiVidEn & PsiVid] and D18F3x128[NbPsiVidEn & NbPsiVid]. |
| 175 | F14PmVrmLowPowerModeEnable (FamilySpecificServices, CpuEarlyParams, StdHeader); |
| 176 | |
| 177 | // Step 3 - Program D18F3xDC[NbPs0Vid] = FCRxFE00_6000[NbPs0Vid] - 1. |
| 178 | // Program D18F3xDC[NbPs0Vid] = FCRxFE00_6000[NbPs0Vid]. |
| 179 | FCRxFE00_6000.Value = NbSmuReadEfuse (FCRxFE00_6000_ADDRESS, StdHeader); |
| 180 | |
| 181 | F14EarlySampleCoreSupport.F14PowerPlaneInitHook (&FCRxFE00_6000, StdHeader); |
| 182 | |
| 183 | PciAddress.AddressValue = CPTC2_PCI_ADDR; |
efdesign98 | 84cbce2 | 2011-08-04 12:09:17 -0600 | [diff] [blame] | 184 | LibAmdPciRead (AccessWidth32, PciAddress, &PciReg, StdHeader); |
| 185 | ((CLK_PWR_TIMING_CTRL2_REGISTER *) &PciReg)->NbPs0Vid = FCRxFE00_6000.Field.NbPs0Vid - 1; |
| 186 | LibAmdPciWrite (AccessWidth32, PciAddress, &PciReg, StdHeader); |
| 187 | ((CLK_PWR_TIMING_CTRL2_REGISTER *) &PciReg)->NbPs0Vid = FCRxFE00_6000.Field.NbPs0Vid; |
| 188 | LibAmdPciWrite (AccessWidth32, PciAddress, &PciReg, StdHeader); |
Frank Vibrans | 2b4c831 | 2011-02-14 18:30:54 +0000 | [diff] [blame] | 189 | } |
| 190 | |
| 191 | /*---------------------------------------------------------------------------------------*/ |
| 192 | /** |
| 193 | * Sets up PSI_L operation. |
| 194 | * |
| 195 | * This function implements the AMD_CPU_EARLY_PARAMS.VrmLowPowerThreshold parameter. |
| 196 | * |
| 197 | * @param[in] FamilySpecificServices The current Family Specific Services. |
| 198 | * @param[in] CpuEarlyParams Contains VrmLowPowerThreshold parameter. |
| 199 | * @param[in] StdHeader Config handle for library and services. |
| 200 | * |
| 201 | */ |
| 202 | VOID |
| 203 | STATIC |
| 204 | F14PmVrmLowPowerModeEnable ( |
| 205 | IN CPU_SPECIFIC_SERVICES *FamilySpecificServices, |
| 206 | IN AMD_CPU_EARLY_PARAMS *CpuEarlyParams, |
| 207 | IN AMD_CONFIG_PARAMS *StdHeader |
| 208 | ) |
| 209 | { |
| 210 | UINT32 Pstate; |
| 211 | UINT32 PstateMaxVal; |
| 212 | UINT32 PstateCurrent; |
| 213 | UINT32 NextPstateCurrent; |
| 214 | UINT32 NextPstateCurrentRaw; |
efdesign98 | 84cbce2 | 2011-08-04 12:09:17 -0600 | [diff] [blame] | 215 | UINT32 PciReg; |
Frank Vibrans | 2b4c831 | 2011-02-14 18:30:54 +0000 | [diff] [blame] | 216 | UINT32 PreviousVid; |
| 217 | UINT32 CurrentVid; |
| 218 | UINT64 PstateMsr; |
| 219 | UINT64 PstateLimitMsr; |
| 220 | BOOLEAN IsPsiEnabled; |
| 221 | PCI_ADDR PciAddress; |
| 222 | |
| 223 | // Set up PSI_L for VDD |
| 224 | IsPsiEnabled = FALSE; |
| 225 | PreviousVid = 0x7F; |
| 226 | CurrentVid = 0x7F; |
| 227 | if (CpuEarlyParams->PlatformConfig.VrmProperties[CoreVrm].LowPowerThreshold != 0) { |
| 228 | LibAmdMsrRead (MSR_PSTATE_CURRENT_LIMIT, &PstateLimitMsr, StdHeader); |
| 229 | PstateMaxVal = (UINT32) ((PSTATE_CURLIM_MSR *) &PstateLimitMsr)->PstateMaxVal; |
| 230 | FamilySpecificServices->GetProcIddMax (FamilySpecificServices, (UINT8) 0, &PstateCurrent, StdHeader); |
| 231 | for (Pstate = 0; Pstate <= PstateMaxVal; Pstate++) { |
| 232 | LibAmdMsrRead ((UINT32) (Pstate + PS_REG_BASE), &PstateMsr, StdHeader); |
| 233 | CurrentVid = (UINT32) ((PSTATE_MSR *) &PstateMsr)->CpuVid; |
| 234 | if (Pstate == PstateMaxVal) { |
| 235 | NextPstateCurrentRaw = 0; |
| 236 | NextPstateCurrent = 0; |
| 237 | } else { |
| 238 | FamilySpecificServices->GetProcIddMax (FamilySpecificServices, (UINT8) (Pstate + 1), &NextPstateCurrentRaw, StdHeader); |
| 239 | NextPstateCurrent = NextPstateCurrentRaw + CpuEarlyParams->PlatformConfig.VrmProperties[CoreVrm].InrushCurrentLimit; |
| 240 | } |
| 241 | if ((PstateCurrent <= CpuEarlyParams->PlatformConfig.VrmProperties[CoreVrm].LowPowerThreshold) && |
| 242 | (NextPstateCurrent <= CpuEarlyParams->PlatformConfig.VrmProperties[CoreVrm].LowPowerThreshold) && |
| 243 | (CurrentVid != PreviousVid)) { |
| 244 | IsPsiEnabled = TRUE; |
| 245 | break; |
| 246 | } else { |
| 247 | PstateCurrent = NextPstateCurrentRaw; |
| 248 | PreviousVid = CurrentVid; |
| 249 | } |
| 250 | } |
| 251 | } |
| 252 | PciAddress.AddressValue = PW_CTL_MISC_PCI_ADDR; |
efdesign98 | 84cbce2 | 2011-08-04 12:09:17 -0600 | [diff] [blame] | 253 | LibAmdPciRead (AccessWidth32, PciAddress, &PciReg, StdHeader); |
Frank Vibrans | 2b4c831 | 2011-02-14 18:30:54 +0000 | [diff] [blame] | 254 | if (IsPsiEnabled) { |
efdesign98 | 84cbce2 | 2011-08-04 12:09:17 -0600 | [diff] [blame] | 255 | ((POWER_CTRL_MISC_REGISTER *) &PciReg)->PsiVid = CurrentVid; |
| 256 | ((POWER_CTRL_MISC_REGISTER *) &PciReg)->PsiVidEn = 1; |
Frank Vibrans | 2b4c831 | 2011-02-14 18:30:54 +0000 | [diff] [blame] | 257 | } else { |
efdesign98 | 84cbce2 | 2011-08-04 12:09:17 -0600 | [diff] [blame] | 258 | ((POWER_CTRL_MISC_REGISTER *) &PciReg)->PsiVidEn = 0; |
Frank Vibrans | 2b4c831 | 2011-02-14 18:30:54 +0000 | [diff] [blame] | 259 | } |
efdesign98 | 84cbce2 | 2011-08-04 12:09:17 -0600 | [diff] [blame] | 260 | LibAmdPciWrite (AccessWidth32, PciAddress, &PciReg, StdHeader); |
Frank Vibrans | 2b4c831 | 2011-02-14 18:30:54 +0000 | [diff] [blame] | 261 | |
| 262 | |
| 263 | // Set up NBPSI_L for VDDNB |
| 264 | PciAddress.AddressValue = CPTC3_PCI_ADDR; |
efdesign98 | 84cbce2 | 2011-08-04 12:09:17 -0600 | [diff] [blame] | 265 | LibAmdPciRead (AccessWidth32, PciAddress, &PciReg, StdHeader); |
Frank Vibrans | 2b4c831 | 2011-02-14 18:30:54 +0000 | [diff] [blame] | 266 | if (CpuEarlyParams->PlatformConfig.VrmProperties[NbVrm].LowPowerThreshold != 0) { |
efdesign98 | 84cbce2 | 2011-08-04 12:09:17 -0600 | [diff] [blame] | 267 | ((CLK_PWR_TIMING_CTRL3_REGISTER *) &PciReg)->NbPsiVid = 0; |
| 268 | ((CLK_PWR_TIMING_CTRL3_REGISTER *) &PciReg)->NbPsiVidEn = 1; |
Frank Vibrans | 2b4c831 | 2011-02-14 18:30:54 +0000 | [diff] [blame] | 269 | } else { |
efdesign98 | 84cbce2 | 2011-08-04 12:09:17 -0600 | [diff] [blame] | 270 | ((CLK_PWR_TIMING_CTRL3_REGISTER *) &PciReg)->NbPsiVidEn = 0; |
Frank Vibrans | 2b4c831 | 2011-02-14 18:30:54 +0000 | [diff] [blame] | 271 | } |
efdesign98 | 84cbce2 | 2011-08-04 12:09:17 -0600 | [diff] [blame] | 272 | LibAmdPciWrite (AccessWidth32, PciAddress, &PciReg, StdHeader); |
Frank Vibrans | 2b4c831 | 2011-02-14 18:30:54 +0000 | [diff] [blame] | 273 | } |