blob: 428924df34a12eeb5015882b02b06f9c02e5592b [file] [log] [blame]
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2007 Advanced Micro Devices, Inc.
Timothy Pearson730a0432015-10-16 13:51:51 -05005 * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000015 */
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000016/*
Stefan Reinauer5ff7c132011-10-31 12:56:45 -070017 * This file initializes the CPU cores for voltage and frequency settings
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000018 * in the different power states.
19 */
20/*
21
22checklist (functions are in this file if no source file named)
Stefan Reinauer5ff7c132011-10-31 12:56:45 -070023Fam10 Bios and Kernel Development Guide #31116, rev 3.48, April 22, 2010
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000024
252.4.2.6 Requirements for p-states
26
271.- F3x[84:80] According to table 100 : prep_fid_change
28
Stefan Reinauer5ff7c132011-10-31 12:56:45 -0700292.- COF/VID :
30 2.4.2.9.1 Steps 1,3-6 and warning for 2,7 if they apply
Elyes HAOUAS2765a892016-09-01 19:44:56 +020031 fixPsNbVidBeforeWR(...)
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000032 2.4.2.9.1 Step 8 enable_fid_change
Elyes HAOUAS2765a892016-09-01 19:44:56 +020033 We do this for all nodes, I don't understand BKDG 100% on
34 whether this is or isn't meant by "on the local
35 processor". Must be OK.
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000036 2.4.2.9.1 Steps 9-10 (repeat 1-7 and reset) romstage.c/init_cpus ?
37 2.4.2.9.1 Steps 11-12 init_fidvid_stage2
Stefan Reinauer5ff7c132011-10-31 12:56:45 -070038 2.4.2.9.2 DualPlane PVI : Not supported, don't know how to detect,
Elyes HAOUAS2765a892016-09-01 19:44:56 +020039 needs specific circuitry.
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000040
413.- 2.4.2.7 dualPlaneOnly(dev)
42
Timothy Pearson730a0432015-10-16 13:51:51 -0500434.- 2.4.2.8 applyBoostFIDOffset(dev, nodeid)
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000044
Stefan Reinauer5ff7c132011-10-31 12:56:45 -0700455.- enableNbPState1(dev)
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000046
Stefan Reinauer5ff7c132011-10-31 12:56:45 -0700476.- 2.4.1.7
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000048 a) UpdateSinglePlaneNbVid()
49 b) setVSRamp(), called from prep_fid_change
50 c) prep_fid_change
Stefan Reinauer5ff7c132011-10-31 12:56:45 -070051 d) improperly, for lack of voltage regulator details?,
Elyes HAOUAS2765a892016-09-01 19:44:56 +020052 F3xA0[PsiVidEn] in defaults.h
53 F3xA0[PsiVid] in init_cpus.c AMD_SetupPSIVID_d (before prep_fid_change)
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000054
Stefan Reinauer5ff7c132011-10-31 12:56:45 -0700557.- TODO (Core Performance Boost is only available in revision E cpus, and we
Elyes HAOUAS2765a892016-09-01 19:44:56 +020056 don't seem to support those yet, at least they don't have any
57 constant in amddefs.h )
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000058
Stefan Reinauer5ff7c132011-10-31 12:56:45 -0700598.- FIXME ? Transition to min Pstate according to 2.4.2.15.3 is required
60 by 2.4.2.6 after warm reset. But 2.4.2.15 states that it is not required
61 if the warm reset is issued by coreboot to update NbFid. So it is required
62 or not ? How can I tell who issued warm reset ?
Martin Rothe18e6422017-06-03 20:03:18 -060063 coreboot transitions to P0 instead, which is not recommended, and does
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000064 not follow 2.4.2.15.2 to do so.
65
Stefan Reinauer5ff7c132011-10-31 12:56:45 -0700669.- TODO Requires information on current delivery capability
67 (depends on mainboard and maybe power supply ?). One might use a config
Martin Roth4c3ab732013-07-08 16:23:54 -060068 option with the maximum number of Amperes that the board can deliver to CPU.
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000069
7010.- [Multiprocessor] TODO 2.4.2.12
Stefan Reinauer5ff7c132011-10-31 12:56:45 -070071 [Uniprocessor] FIXME ? We call setPStateMaxVal() in init_fidvid_stage2,
72 but not sure this is what is meant by "Determine the valid set of
73 P-states based on enabled P-states indicated
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000074 in MSRC001_00[68:64][PstateEn]" in 2.4.2.6-10
75
7611.- finalPstateChange() from init_fidvid_Stage2 (BKDG says just "may", anyway)
77
Timothy Pearsona89accd2015-02-20 11:54:09 -06007812.- generate ACPI for p-states.
Patrick Georgia425b962015-03-05 20:18:21 +010079 generated in powernow_acpi.c amd_generate_powernow()
Stefan Reinauer5ff7c132011-10-31 12:56:45 -070080
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000081"must also be completed"
82
83a.- PllLockTime set in ruleset in defaults.h
Stefan Reinauer5ff7c132011-10-31 12:56:45 -070084 BKDG says set it "If MSRC001_00[68:64][CpuFid] is different between
85 any two enabled P-states", but since it does not say "only if"
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000086 I guess it is safe to do it always.
87
88b.- prep_fid_change(...)
89
90 */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000091
Elyes HAOUAS400ce552018-10-12 10:54:30 +020092#include <cpu/amd/msr.h>
Damien Zammit75a3d1f2016-11-28 00:29:10 +110093#include <inttypes.h>
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000094#include <northbridge/amd/amdht/AsPsDefs.h>
95
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000096static inline void print_debug_fv(const char *str, u32 val)
97{
Martin Roth5f46af62017-06-24 13:24:26 -060098#if IS_ENABLED(CONFIG_SET_FIDVID_DEBUG)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000099 printk(BIOS_DEBUG, "%s%x\n", str, val);
100#endif
101}
102
103static inline void print_debug_fv_8(const char *str, u8 val)
104{
Martin Roth5f46af62017-06-24 13:24:26 -0600105#if IS_ENABLED(CONFIG_SET_FIDVID_DEBUG)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000106 printk(BIOS_DEBUG, "%s%02x\n", str, val);
107#endif
108}
109
110static inline void print_debug_fv_64(const char *str, u32 val, u32 val2)
111{
Martin Roth5f46af62017-06-24 13:24:26 -0600112#if IS_ENABLED(CONFIG_SET_FIDVID_DEBUG)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000113 printk(BIOS_DEBUG, "%s%x%x\n", str, val, val2);
114#endif
115}
116
117struct fidvid_st {
118 u32 common_fid;
119};
120
121static void enable_fid_change(u8 fid)
122{
123 u32 dword;
124 u32 nodes;
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200125 pci_devfn_t dev;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000126 int i;
127
128 nodes = get_nodes();
129
130 for (i = 0; i < nodes; i++) {
131 dev = NODE_PCI(i, 3);
132 dword = pci_read_config32(dev, 0xd4);
133 dword &= ~0x1F;
134 dword |= (u32) fid & 0x1F;
135 dword |= 1 << 5; // enable
136 pci_write_config32(dev, 0xd4, dword);
Elyes HAOUAS7c8d74c2016-08-23 21:41:43 +0200137 printk(BIOS_DEBUG, "FID Change Node:%02x, F3xD4: %08x\n", i,
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000138 dword);
139 }
140}
Xavi Drudis Ferran5bcedee2011-02-28 03:25:07 +0000141
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200142static void applyBoostFIDOffset(pci_devfn_t dev, uint32_t nodeid)
143{
Timothy Pearson730a0432015-10-16 13:51:51 -0500144 // BKDG 2.4.2.8
145 // Fam10h revision E only, but E is apparently not supported yet, therefore untested
146 if ((cpuid_edx(0x80000007) & CPB_MASK)
147 && ((cpuid_ecx(0x80000008) & NC_MASK) == 5) ) {
148 u32 core = get_node_core_id_x().coreid;
149 u32 asymetricBoostThisCore = ((pci_read_config32(dev, 0x10C) >> (core*2))) & 3;
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200150 msr_t msr = rdmsr(PSTATE_0_MSR);
Timothy Pearson730a0432015-10-16 13:51:51 -0500151 u32 cpuFid = msr.lo & PS_CPU_FID_MASK;
152 cpuFid = cpuFid + asymetricBoostThisCore;
153 msr.lo &= ~PS_CPU_FID_MASK;
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200154 msr.lo |= cpuFid;
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200155 wrmsr(PSTATE_0_MSR, msr);
Timothy Pearson730a0432015-10-16 13:51:51 -0500156 } else if (is_fam15h()) {
157 uint32_t dword = pci_read_config32(NODE_PCI(nodeid, 4), 0x15c);
158 uint8_t boost_count = (dword >> 2) & 0x7;
159 if (boost_count > 0) {
160 /* Enable boost */
161 dword &= ~0x3;
162 dword |= 0x1;
163 pci_write_config32(NODE_PCI(nodeid, 4), 0x15c, dword);
164 }
165 }
Xavi Drudis Ferran5bcedee2011-02-28 03:25:07 +0000166}
167
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200168static void enableNbPState1(pci_devfn_t dev)
169{
Timothy Pearson83abd812015-06-08 19:35:06 -0500170 uint64_t cpuRev = mctGetLogicalCPUID(0xFF);
171 if (cpuRev & AMD_FAM10_C3) {
172 u32 nbPState = (pci_read_config32(dev, 0x1F0) & NB_PSTATE_MASK);
173 if ( nbPState){
174 u32 nbVid1 = (pci_read_config32(dev, 0x1F4) & NB_VID1_MASK) >> NB_VID1_SHIFT;
175 u32 i;
176 for (i = nbPState; i < NM_PS_REG; i++) {
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200177 msr_t msr = rdmsr(PSTATE_0_MSR + i);
Timothy Pearson83abd812015-06-08 19:35:06 -0500178 if (msr.hi & PS_EN_MASK ) {
179 msr.hi |= NB_DID_M_ON;
180 msr.lo &= NB_VID_MASK_OFF;
181 msr.lo |= ( nbVid1 << NB_VID_POS);
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200182 wrmsr(PSTATE_0_MSR + i, msr);
Timothy Pearson83abd812015-06-08 19:35:06 -0500183 }
184 }
185 }
186 }
Xavi Drudis Ferrane80ce0a2011-02-28 03:12:00 +0000187}
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000188
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200189static u8 setPStateMaxVal(pci_devfn_t dev)
190{
Timothy Pearson83abd812015-06-08 19:35:06 -0500191 u8 i, maxpstate=0;
192 for (i = 0; i < NM_PS_REG; i++) {
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200193 msr_t msr = rdmsr(PSTATE_0_MSR + i);
Timothy Pearson83abd812015-06-08 19:35:06 -0500194 if (msr.hi & PS_IDD_VALUE_MASK) {
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200195 msr.hi |= PS_EN_MASK;
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200196 wrmsr(PSTATE_0_MSR + i, msr);
Timothy Pearson83abd812015-06-08 19:35:06 -0500197 }
198 if (msr.hi & PS_EN_MASK) {
199 maxpstate = i;
200 }
201 }
202 //FIXME: CPTC2 and HTC_REG should get max per node, not per core ?
203 u32 reg = pci_read_config32(dev, CPTC2);
204 reg &= PS_MAX_VAL_MASK;
205 reg |= (maxpstate << PS_MAX_VAL_POS);
206 pci_write_config32(dev, CPTC2,reg);
207 return maxpstate;
Xavi Drudis Ferrance623502011-02-28 03:19:17 +0000208}
209
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200210static void dualPlaneOnly(pci_devfn_t dev)
211{
Timothy Pearson83abd812015-06-08 19:35:06 -0500212 // BKDG 2.4.2.7
Xavi Drudis Ferrance623502011-02-28 03:19:17 +0000213
Timothy Pearson83abd812015-06-08 19:35:06 -0500214 uint64_t cpuRev = mctGetLogicalCPUID(0xFF);
215 if ((mctGetProcessorPackageType() == AMD_PKGTYPE_AM3_2r2)
216 && (cpuRev & (AMD_DR_Cx | AMD_DR_Ex))) {
217 if ((pci_read_config32(dev, 0x1FC) & DUAL_PLANE_ONLY_MASK)
218 && (pci_read_config32(dev, 0xA0) & PVI_MODE)) {
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200219 if (cpuid_edx(CPUID_EXT_PM) & CPB_MASK) {
Timothy Pearson83abd812015-06-08 19:35:06 -0500220 // revision E only, but E is apparently not supported yet, therefore untested
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200221 msr_t minPstate = rdmsr(PSTATE_1_MSR);
222 wrmsr(PSTATE_1_MSR, rdmsr(PSTATE_4_MSR));
223 wrmsr(PSTATE_4_MSR, minPstate);
Timothy Pearson83abd812015-06-08 19:35:06 -0500224 } else {
225 msr_t msr;
226 msr.lo=0; msr.hi=0;
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200227 wrmsr(PSTATE_0_MSR, rdmsr(PSTATE_4_MSR));
228 wrmsr(PSTATE_4_MSR, msr);
Timothy Pearson83abd812015-06-08 19:35:06 -0500229 }
Xavi Drudis Ferranc3132102011-02-28 03:49:28 +0000230
Timothy Pearson83abd812015-06-08 19:35:06 -0500231 //FIXME: CPTC2 and HTC_REG should get max per node, not per core ?
232 u8 maxpstate = setPStateMaxVal(dev);
Xavi Drudis Ferrance623502011-02-28 03:19:17 +0000233
Timothy Pearson83abd812015-06-08 19:35:06 -0500234 u32 reg = pci_read_config32(dev, HTC_REG);
235 reg &= HTC_PS_LMT_MASK;
236 reg |= (maxpstate << PS_LIMIT_POS);
237 pci_write_config32(dev, HTC_REG,reg);
238 }
239 }
Xavi Drudis Ferrance623502011-02-28 03:19:17 +0000240}
241
Xavi Drudis Ferranc3132102011-02-28 03:49:28 +0000242static int vidTo100uV(u8 vid)
Timothy Pearson83abd812015-06-08 19:35:06 -0500243{
244 // returns voltage corresponding to vid in tenths of mV, i.e. hundreds of uV
245 // BKDG #31116 rev 3.48 2.4.1.6
246 int voltage;
247 if (vid >= 0x7c) {
248 voltage = 0;
249 } else {
250 voltage = (15500 - (125*vid));
251 }
252 return voltage;
Xavi Drudis Ferran82b241a2011-02-28 03:32:23 +0000253}
254
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200255static void setVSRamp(pci_devfn_t dev)
256{
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000257 /* BKDG r31116 2010-04-22 2.4.1.7 step b F3xD8[VSRampTime]
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200258 * If this field accepts 8 values between 10 and 500 us why
259 * does page 324 say "BIOS should set this field to 001b."
260 * (20 us) ?
261 * Shouldn't it depend on the voltage regulators, mainboard
262 * or something ?
263 */
264 u32 dword;
Xavi Drudis Ferrand7294592011-02-27 23:42:58 +0000265 dword = pci_read_config32(dev, 0xd8);
266 dword &= VSRAMP_MASK;
267 dword |= VSRAMP_VALUE;
268 pci_write_config32(dev, 0xd8, dword);
269}
270
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200271static void recalculateVsSlamTimeSettingOnCorePre(pci_devfn_t dev)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000272{
273 u8 pviModeFlag;
274 u8 highVoltageVid, lowVoltageVid, bValue;
275 u16 minimumSlamTime;
276 u16 vSlamTimes[7] = { 1000, 2000, 3000, 4000, 6000, 10000, 20000 }; /* Reg settings scaled by 100 */
277 u32 dtemp;
278 msr_t msr;
279
280 /* This function calculates the VsSlamTime using the range of possible
281 * voltages instead of a hardcoded 200us.
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200282 * Note: his function is called only from prep_fid_change,
283 * and that from init_cpus.c finalize_node_setup()
284 * (after set AMD MSRs and init ht )
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000285 */
286
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200287 /* BKDG r31116 2010-04-22 2.4.1.7 step b F3xD8[VSSlamTime] */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000288 /* Calculate Slam Time
Xavi Drudis Ferran82b241a2011-02-28 03:32:23 +0000289 * Vslam = (mobileCPU?0.2:0.4)us/mV * (Vp0 - (lowest out of Vpmin or Valt)) mV
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000290 * In our case, we will scale the values by 100 to avoid
291 * decimals.
292 */
293
294 /* Determine if this is a PVI or SVI system */
Timothy Pearson730a0432015-10-16 13:51:51 -0500295 if (is_fam15h()) {
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000296 pviModeFlag = 0;
Timothy Pearson730a0432015-10-16 13:51:51 -0500297 } else {
298 dtemp = pci_read_config32(dev, 0xa0);
299
300 if (dtemp & PVI_MODE)
301 pviModeFlag = 1;
302 else
303 pviModeFlag = 0;
304 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000305
306 /* Get P0's voltage */
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200307 /* MSRC001_00[68:64] are not programmed yet when called from
Xavi Drudis Ferran82b241a2011-02-28 03:32:23 +0000308 prep_fid_change, one might use F4x1[F0:E0] instead, but
309 theoretically MSRC001_00[68:64] are equal to them after
310 reset. */
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200311 msr = rdmsr(PSTATE_0_MSR);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000312 highVoltageVid = (u8) ((msr.lo >> PS_CPU_VID_SHFT) & 0x7F);
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200313 if (!(msr.hi & 0x80000000)) {
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600314 printk(BIOS_ERR,"P-state info in MSRC001_0064 is invalid !!!\n");
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200315 highVoltageVid = (u8) ((pci_read_config32(dev, 0x1E0)
316 >> PS_CPU_VID_SHFT) & 0x7F);
Xavi Drudis Ferran82b241a2011-02-28 03:32:23 +0000317 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000318
319 /* If SVI, we only care about CPU VID.
320 * If PVI, determine the higher voltage b/t NB and CPU
321 */
322 if (pviModeFlag) {
323 bValue = (u8) ((msr.lo >> PS_NB_VID_SHFT) & 0x7F);
324 if (highVoltageVid > bValue)
325 highVoltageVid = bValue;
326 }
327
Xavi Drudis Ferran82b241a2011-02-28 03:32:23 +0000328 /* Get PSmax's index */
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200329 msr = rdmsr(PS_LIM_REG);
Xavi Drudis Ferran82b241a2011-02-28 03:32:23 +0000330 bValue = (u8) ((msr.lo >> PS_MAX_VAL_SHFT) & BIT_MASK_3);
Xavi Drudis Ferranc3132102011-02-28 03:49:28 +0000331
Xavi Drudis Ferran82b241a2011-02-28 03:32:23 +0000332 /* Get PSmax's VID */
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200333 msr = rdmsr(PSTATE_0_MSR + bValue);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000334 lowVoltageVid = (u8) ((msr.lo >> PS_CPU_VID_SHFT) & 0x7F);
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200335 if (!(msr.hi & 0x80000000)) {
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200336 printk(BIOS_ERR, "P-state info in MSR%8x is invalid !!!\n",
337 PSTATE_0_MSR + bValue);
338 lowVoltageVid = (u8) ((pci_read_config32(dev, 0x1E0+(bValue*4))
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200339 >> PS_CPU_VID_SHFT) & 0x7F);
Xavi Drudis Ferran82b241a2011-02-28 03:32:23 +0000340 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000341
342 /* If SVI, we only care about CPU VID.
343 * If PVI, determine the higher voltage b/t NB and CPU
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200344 * BKDG 2.4.1.7 (a)
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600345 */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000346 if (pviModeFlag) {
347 bValue = (u8) ((msr.lo >> PS_NB_VID_SHFT) & 0x7F);
348 if (lowVoltageVid > bValue)
349 lowVoltageVid = bValue;
350 }
351
352 /* Get AltVID */
Timothy Pearson83abd812015-06-08 19:35:06 -0500353 dtemp = pci_read_config32(dev, 0xdc);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000354 bValue = (u8) (dtemp & BIT_MASK_7);
355
356 /* Use the VID with the lowest voltage (higher VID) */
357 if (lowVoltageVid < bValue)
358 lowVoltageVid = bValue;
359
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200360 u8 mobileFlag = get_platform_type() & AMD_PTYPE_MOB;
Xavi Drudis Ferran82b241a2011-02-28 03:32:23 +0000361 minimumSlamTime = (mobileFlag?2:4) * (vidTo100uV(highVoltageVid) - vidTo100uV(lowVoltageVid)); /* * 0.01 us */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000362
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000363
364 /* Now round up to nearest register setting.
365 * Note that if we don't find a value, we
366 * will fall through to a value of 7
367 */
368 for (bValue = 0; bValue < 7; bValue++) {
369 if (minimumSlamTime <= vSlamTimes[bValue])
370 break;
371 }
372
373 /* Apply the value */
374 dtemp = pci_read_config32(dev, 0xD8);
375 dtemp &= VSSLAM_MASK;
376 dtemp |= bValue;
377 pci_write_config32(dev, 0xd8, dtemp);
378}
379
Timothy Pearson5173bb72015-08-02 21:31:48 -0500380static u32 nb_clk_did(uint8_t node, uint64_t cpuRev, uint8_t procPkg) {
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200381 uint8_t link0isGen3 = 0;
382 uint8_t offset;
383 if (AMD_CpuFindCapability(node, 0, &offset)) {
Timothy Pearsonf8549e82015-09-07 22:26:55 -0500384 link0isGen3 = (AMD_checkLinkType(node, offset) & HTPHY_LINKTYPE_HT3 );
Xavi Drudis Ferranadb23a52011-02-28 00:10:37 +0000385 }
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200386 /* FIXME: NB_CLKDID should be 101b for AMD_DA_C2 in package
387 S1g3 in link Gen3 mode, but I don't know how to tell
388 package S1g3 from S1g4 */
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000389 if ((cpuRev & AMD_DA_C2) && (procPkg & AMD_PKGTYPE_S1gX)
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200390 && link0isGen3) {
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200391 return 5; /* divide clk by 128*/
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200392 } else {
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200393 return 4; /* divide clk by 16 */
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200394 }
Xavi Drudis Ferranadb23a52011-02-28 00:10:37 +0000395}
396
397
398static u32 power_up_down(int node, u8 procPkg) {
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600399 uint32_t dword=0;
400 /* from CPU rev guide #41322 rev 3.74 June 2010 Table 26 */
401 u8 singleLinkFlag = ((procPkg == AMD_PKGTYPE_AM3_2r2)
402 || (procPkg == AMD_PKGTYPE_S1gX)
403 || (procPkg == AMD_PKGTYPE_ASB2));
Xavi Drudis Ferranadb23a52011-02-28 00:10:37 +0000404
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600405 if (singleLinkFlag) {
406 /*
407 * PowerStepUp=01000b - 50nS
408 * PowerStepDown=01000b - 50ns
Xavi Drudis Ferrana5cbd252011-02-27 23:45:34 +0000409 */
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600410 dword |= PW_STP_UP50 | PW_STP_DN50;
411 } else {
412 uint32_t dispRefModeEn = (pci_read_config32(NODE_PCI(node,0),0x68) >> 24) & 1;
413 uint32_t isocEn = 0;
414 int j;
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200415 for (j=0; (j<4) && (!isocEn); j++ ) {
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600416 u8 offset;
417 if (AMD_CpuFindCapability(node, j, &offset)) {
418 isocEn = (pci_read_config32(NODE_PCI(node,0),offset+4) >>12) & 1;
419 }
Xavi Drudis Ferrana5cbd252011-02-27 23:45:34 +0000420 }
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600421
422 if (is_fam15h()) {
423 /* Family 15h always uses 100ns for multilink processors */
424 dword |= PW_STP_UP100 | PW_STP_DN100;
425 } else if (dispRefModeEn || isocEn) {
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200426 dword |= PW_STP_UP50 | PW_STP_DN50;
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600427 } else {
428 /* get number of cores for PowerStepUp & PowerStepDown in server
429 * 1 core - 400nS - 0000b
430 * 2 cores - 200nS - 0010b
431 * 3 cores - 133nS -> 100nS - 0011b
432 * 4 cores - 100nS - 0011b
433 */
434 switch (get_core_num_in_bsp(node)) {
435 case 0:
436 dword |= PW_STP_UP400 | PW_STP_DN400;
437 break;
438 case 1:
439 case 2:
440 dword |= PW_STP_UP200 | PW_STP_DN200;
441 break;
442 case 3:
443 dword |= PW_STP_UP100 | PW_STP_DN100;
444 break;
445 default:
446 dword |= PW_STP_UP100 | PW_STP_DN100;
447 break;
448 }
449 }
Xavi Drudis Ferrana5cbd252011-02-27 23:45:34 +0000450 }
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600451
452 return dword;
Xavi Drudis Ferrand26e5e62011-02-27 23:56:00 +0000453}
454
Timothy Pearson5173bb72015-08-02 21:31:48 -0500455static void config_clk_power_ctrl_reg0(uint8_t node, uint64_t cpuRev, uint8_t procPkg) {
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200456
457 pci_devfn_t dev = NODE_PCI(node, 3);
Xavi Drudis Ferrand26e5e62011-02-27 23:56:00 +0000458
Xavi Drudis Ferrand26e5e62011-02-27 23:56:00 +0000459 /* Program fields in Clock Power/Control register0 (F3xD4) */
460
461 /* set F3xD4 Clock Power/Timing Control 0 Register
462 * NbClkDidApplyAll=1b
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000463 * NbClkDid=100b or 101b
Xavi Drudis Ferrand26e5e62011-02-27 23:56:00 +0000464 * PowerStepUp= "platform dependent"
465 * PowerStepDown= "platform dependent"
466 * LinkPllLink=01b
Xavi Drudis Ferranadb23a52011-02-28 00:10:37 +0000467 * ClkRampHystCtl=HW default
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200468 * ClkRampHystSel=1111b
Xavi Drudis Ferrand26e5e62011-02-27 23:56:00 +0000469 */
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200470 uint32_t dword= pci_read_config32(dev, 0xd4);
Xavi Drudis Ferrand26e5e62011-02-27 23:56:00 +0000471 dword &= CPTC0_MASK;
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200472 dword |= NB_CLKDID_ALL | LNK_PLL_LOCK | CLK_RAMP_HYST_SEL_VAL;
473 dword |= (nb_clk_did(node,cpuRev,procPkg) << NB_CLKDID_SHIFT);
Xavi Drudis Ferranadb23a52011-02-28 00:10:37 +0000474
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200475 dword |= power_up_down(node, procPkg);
Xavi Drudis Ferrand26e5e62011-02-27 23:56:00 +0000476
477 pci_write_config32(dev, 0xd4, dword);
478
Xavi Drudis Ferrana5cbd252011-02-27 23:45:34 +0000479}
480
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200481static void config_power_ctrl_misc_reg(pci_devfn_t dev, uint64_t cpuRev,
482 uint8_t procPkg)
483{
Xavi Drudis Ferran9683b1d2011-02-27 23:47:57 +0000484 /* check PVI/SVI */
Timothy Pearson5173bb72015-08-02 21:31:48 -0500485 uint32_t dword = pci_read_config32(dev, 0xa0);
Xavi Drudis Ferran0e5d3e12011-02-28 00:18:43 +0000486
Timothy Pearson38629f52015-09-05 18:46:54 -0500487 /* BKDG r31116 2010-04-22 2.4.1.7 step b F3xA0[VSSlamVidMod] */
488 /* PllLockTime and PsiVidEn set in ruleset in defaults.h */
Xavi Drudis Ferran9683b1d2011-02-27 23:47:57 +0000489 if (dword & PVI_MODE) { /* PVI */
490 /* set slamVidMode to 0 for PVI */
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200491 dword &= VID_SLAM_OFF;
Xavi Drudis Ferran9683b1d2011-02-27 23:47:57 +0000492 } else { /* SVI */
493 /* set slamVidMode to 1 for SVI */
Xavi Drudis Ferran0e5d3e12011-02-28 00:18:43 +0000494 dword |= VID_SLAM_ON;
Timothy Pearson38629f52015-09-05 18:46:54 -0500495 }
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200496 /* set the rest of A0 since we're at it... */
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000497
Timothy Pearson38629f52015-09-05 18:46:54 -0500498 if (cpuRev & (AMD_DA_Cx | AMD_RB_C3 )) {
499 dword |= NB_PSTATE_FORCE_ON;
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000500 } // else should we clear it ?
Xavi Drudis Ferran0e5d3e12011-02-28 00:18:43 +0000501
502
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200503 if ((procPkg == AMD_PKGTYPE_G34) || (procPkg == AMD_PKGTYPE_C32) ) {
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200504 dword |= BP_INS_TRI_EN_ON;
Xavi Drudis Ferran9683b1d2011-02-27 23:47:57 +0000505 }
Xavi Drudis Ferran0e5d3e12011-02-28 00:18:43 +0000506
507 /* TODO: look into C1E state and F3xA0[IdleExitEn]*/
Martin Roth5f46af62017-06-24 13:24:26 -0600508 #if IS_ENABLED(CONFIG_SVI_HIGH_FREQ)
Timothy Pearson38629f52015-09-05 18:46:54 -0500509 if (cpuRev & AMD_FAM10_C3) {
510 dword |= SVI_HIGH_FREQ_ON;
511 }
512 #endif
513 pci_write_config32(dev, 0xa0, dword);
Xavi Drudis Ferran9683b1d2011-02-27 23:47:57 +0000514}
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000515
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200516static void config_nb_syn_ptr_adj(pci_devfn_t dev, uint64_t cpuRev)
517{
Xavi Drudis Ferran1d80e512011-02-27 23:50:30 +0000518 /* Note the following settings are additional from the ported
519 * function setFidVidRegs()
520 */
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200521 /* adjust FIFO between nb and core clocks to max allowed
522 values (min latency) */
Timothy Pearson5173bb72015-08-02 21:31:48 -0500523 uint32_t nbPstate = pci_read_config32(dev,0x1f0) & NB_PSTATE_MASK;
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200524 uint8_t nbSynPtrAdj;
Timothy Pearson83abd812015-06-08 19:35:06 -0500525 if ((cpuRev & (AMD_DR_Bx | AMD_DA_Cx | AMD_FAM15_ALL) )
526 || ((cpuRev & AMD_RB_C3) && (nbPstate != 0))) {
527 nbSynPtrAdj = 5;
Xavi Drudis Ferran1f93fea2011-02-28 00:24:21 +0000528 } else {
Timothy Pearson83abd812015-06-08 19:35:06 -0500529 nbSynPtrAdj = 6;
Xavi Drudis Ferran1f93fea2011-02-28 00:24:21 +0000530 }
Xavi Drudis Ferran1d80e512011-02-27 23:50:30 +0000531
Timothy Pearson5173bb72015-08-02 21:31:48 -0500532 uint32_t dword = pci_read_config32(dev, 0xdc);
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200533 dword &= ~NB_SYN_PTR_ADJ_MASK;
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000534 dword |= nbSynPtrAdj << NB_SYN_PTR_ADJ_POS;
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200535 /* NbsynPtrAdj set to 5 or 6 per BKDG (needs reset) */
Xavi Drudis Ferran1f93fea2011-02-28 00:24:21 +0000536 pci_write_config32(dev, 0xdc, dword);
Xavi Drudis Ferran1d80e512011-02-27 23:50:30 +0000537}
538
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200539static void config_acpi_pwr_state_ctrl_regs(pci_devfn_t dev, uint64_t cpuRev,
540 uint8_t procPkg)
541{
Timothy Pearson730a0432015-10-16 13:51:51 -0500542 if (is_fam15h()) {
543 /* Family 15h BKDG Rev. 3.14 D18F3x80 recommended settings */
544 pci_write_config32(dev, 0x80, 0xe20be281);
Xavi Drudis Ferran6fcc9612011-02-28 00:31:24 +0000545
Timothy Pearson730a0432015-10-16 13:51:51 -0500546 /* Family 15h BKDG Rev. 3.14 D18F3x84 recommended settings */
547 pci_write_config32(dev, 0x84, 0x01e200e2);
548 } else {
549 /* step 1, chapter 2.4.2.6 of AMD Fam 10 BKDG #31116 Rev 3.48 22.4.2010 */
Timothy Pearson5173bb72015-08-02 21:31:48 -0500550 uint32_t dword;
551 uint32_t c1= 1;
Timothy Pearson730a0432015-10-16 13:51:51 -0500552 if (cpuRev & (AMD_DR_Bx)) {
553 // will coreboot ever enable cache scrubbing ?
554 // if it does, will it be enough to check the current state
555 // or should we configure for what we'll set up later ?
556 dword = pci_read_config32(dev, 0x58);
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600557 uint32_t scrubbingCache = dword &
Timothy Pearson730a0432015-10-16 13:51:51 -0500558 ( (0x1F << 16) // DCacheScrub
559 | (0x1F << 8) ); // L2Scrub
560 if (scrubbingCache) {
561 c1 = 0x80;
562 } else {
563 c1 = 0xA0;
564 }
565 } else { // rev C or later
566 // same doubt as cache scrubbing: ok to check current state ?
Timothy Pearson83abd812015-06-08 19:35:06 -0500567 dword = pci_read_config32(dev, 0xdc);
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600568 uint32_t cacheFlushOnHalt = dword & (7 << 16);
Timothy Pearson730a0432015-10-16 13:51:51 -0500569 if (!cacheFlushOnHalt) {
570 c1 = 0x80;
571 }
572 }
573 dword = (c1 << 24) | (0xE641E6);
574 pci_write_config32(dev, 0x84, dword);
Xavi Drudis Ferran6fcc9612011-02-28 00:31:24 +0000575
Timothy Pearson730a0432015-10-16 13:51:51 -0500576 /* FIXME: BKDG Table 100 says if the link is at a Gen1
577 * frequency and the chipset does not support a 10us minimum LDTSTOP
578 * assertion time, then { If ASB2 && SVI then smaf001 = F6h else
579 * smaf001=87h. } else ... I hardly know what it means or how to check
580 * it from here, so I bluntly assume it is false and code here the else,
581 * which is easier
582 */
Xavi Drudis Ferran6fcc9612011-02-28 00:31:24 +0000583
Timothy Pearson5173bb72015-08-02 21:31:48 -0500584 uint32_t smaf001 = 0xE6;
Timothy Pearson730a0432015-10-16 13:51:51 -0500585 if (cpuRev & AMD_DR_Bx ) {
586 smaf001 = 0xA6;
587 } else {
Martin Roth5f46af62017-06-24 13:24:26 -0600588 #if IS_ENABLED(CONFIG_SVI_HIGH_FREQ)
Timothy Pearson730a0432015-10-16 13:51:51 -0500589 if (cpuRev & (AMD_RB_C3 | AMD_DA_C3)) {
590 smaf001 = 0xF6;
591 }
592 #endif
593 }
Timothy Pearson5173bb72015-08-02 21:31:48 -0500594 uint32_t fidvidChange = 0;
Timothy Pearson730a0432015-10-16 13:51:51 -0500595 if (((cpuRev & AMD_DA_Cx) && (procPkg & AMD_PKGTYPE_S1gX))
596 || (cpuRev & AMD_RB_C3) ) {
597 fidvidChange=0x0B;
598 }
599 dword = (0xE6 << 24) | (fidvidChange << 16)
600 | (smaf001 << 8) | 0x81;
601 pci_write_config32(dev, 0x80, dword);
602 }
Xavi Drudis Ferran40f9b4b02011-02-27 23:53:11 +0000603}
604
Damien Zammit75a3d1f2016-11-28 00:29:10 +1100605void prep_fid_change(void)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000606{
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200607 u32 dword;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000608 u32 nodes;
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200609 pci_devfn_t dev;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000610 int i;
611
612 /* This needs to be run before any Pstate changes are requested */
613
614 nodes = get_nodes();
615
616 for (i = 0; i < nodes; i++) {
Timothy Pearson38629f52015-09-05 18:46:54 -0500617 printk(BIOS_DEBUG, "Prep FID/VID Node:%02x\n", i);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000618 dev = NODE_PCI(i, 3);
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200619 uint64_t cpuRev = mctGetLogicalCPUID(0xFF);
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200620 u8 procPkg = mctGetProcessorPackageType();
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000621
Xavi Drudis Ferrand7294592011-02-27 23:42:58 +0000622 setVSRamp(dev);
623 /* BKDG r31116 2010-04-22 2.4.1.7 step b F3xD8[VSSlamTime] */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000624 /* Figure out the value for VsSlamTime and program it */
625 recalculateVsSlamTimeSettingOnCorePre(dev);
626
Timothy Pearson38629f52015-09-05 18:46:54 -0500627 config_clk_power_ctrl_reg0(i,cpuRev,procPkg);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000628
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200629 config_power_ctrl_misc_reg(dev,cpuRev,procPkg);
Xavi Drudis Ferran1f93fea2011-02-28 00:24:21 +0000630 config_nb_syn_ptr_adj(dev,cpuRev);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000631
Timothy Pearson38629f52015-09-05 18:46:54 -0500632 config_acpi_pwr_state_ctrl_regs(dev,cpuRev,procPkg);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000633
634 dword = pci_read_config32(dev, 0x80);
Timothy Pearson38629f52015-09-05 18:46:54 -0500635 printk(BIOS_DEBUG, " F3x80: %08x\n", dword);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000636 dword = pci_read_config32(dev, 0x84);
Timothy Pearson38629f52015-09-05 18:46:54 -0500637 printk(BIOS_DEBUG, " F3x84: %08x\n", dword);
Timothy Pearson83abd812015-06-08 19:35:06 -0500638 dword = pci_read_config32(dev, 0xd4);
Timothy Pearson38629f52015-09-05 18:46:54 -0500639 printk(BIOS_DEBUG, " F3xD4: %08x\n", dword);
Timothy Pearson83abd812015-06-08 19:35:06 -0500640 dword = pci_read_config32(dev, 0xd8);
Timothy Pearson38629f52015-09-05 18:46:54 -0500641 printk(BIOS_DEBUG, " F3xD8: %08x\n", dword);
Timothy Pearson83abd812015-06-08 19:35:06 -0500642 dword = pci_read_config32(dev, 0xdc);
Timothy Pearson38629f52015-09-05 18:46:54 -0500643 printk(BIOS_DEBUG, " F3xDC: %08x\n", dword);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000644 }
645}
646
Timothy Pearson730a0432015-10-16 13:51:51 -0500647static void waitCurrentPstate(u32 target_pstate) {
Timothy Pearson0122afb2015-07-30 14:07:15 -0500648 msr_t initial_msr = rdmsr(TSC_MSR);
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200649 msr_t pstate_msr = rdmsr(PS_STS_REG);
Timothy Pearson0122afb2015-07-30 14:07:15 -0500650 msr_t tsc_msr;
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200651 u8 timedout;
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000652
Timothy Pearson0122afb2015-07-30 14:07:15 -0500653 /* paranoia ? I fear when we run fixPsNbVidBeforeWR we can enter a
654 * P1 that is a copy of P0, therefore has the same NB DID but the
655 * TSC will count twice per tick, so we have to wait for twice the
656 * count to achieve the desired timeout. But I'm likely to
657 * misunderstand this...
658 */
659 u32 corrected_timeout = ((pstate_msr.lo==1)
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200660 && (!(rdmsr(PSTATE_1_MSR).lo & NB_DID_M_ON))) ?
Timothy Pearson0122afb2015-07-30 14:07:15 -0500661 WAIT_PSTATE_TIMEOUT*2 : WAIT_PSTATE_TIMEOUT;
662 msr_t timeout;
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000663
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200664 timeout.lo = initial_msr.lo + corrected_timeout;
Timothy Pearson0122afb2015-07-30 14:07:15 -0500665 timeout.hi = initial_msr.hi;
666 if ( (((u32)0xffffffff) - initial_msr.lo) < corrected_timeout ) {
667 timeout.hi++;
668 }
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000669
Timothy Pearson0122afb2015-07-30 14:07:15 -0500670 // assuming TSC ticks at 1.25 ns per tick (800 MHz)
671 do {
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200672 pstate_msr = rdmsr(PS_STS_REG);
Timothy Pearson0122afb2015-07-30 14:07:15 -0500673 tsc_msr = rdmsr(TSC_MSR);
674 timedout = (tsc_msr.hi > timeout.hi)
675 || ((tsc_msr.hi == timeout.hi) && (tsc_msr.lo > timeout.lo ));
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200676 } while ( (pstate_msr.lo != target_pstate) && (! timedout) );
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000677
Timothy Pearson0122afb2015-07-30 14:07:15 -0500678 if (pstate_msr.lo != target_pstate) {
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200679 msr_t limit_msr = rdmsr(PS_LIM_REG);
Timothy Pearson0122afb2015-07-30 14:07:15 -0500680 printk(BIOS_ERR, "*** APIC ID %02x: timed out waiting for P-state %01x. Current P-state %01x P-state current limit MSRC001_0061=%08x %08x\n",
681 cpuid_ebx(0x00000001) >> 24, target_pstate, pstate_msr.lo, limit_msr.hi, limit_msr.lo);
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000682
Timothy Pearson0122afb2015-07-30 14:07:15 -0500683 do { // should we just go on instead ?
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200684 pstate_msr = rdmsr(PS_STS_REG);
Elyes HAOUASa342f392018-10-17 10:56:26 +0200685 } while (pstate_msr.lo != target_pstate);
Timothy Pearson0122afb2015-07-30 14:07:15 -0500686 }
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000687}
688
689static void set_pstate(u32 nonBoostedPState) {
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600690 msr_t msr;
691 uint8_t skip_wait;
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000692
693 // Transition P0 for calling core.
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200694 msr = rdmsr(PS_CTL_REG);
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000695
696 msr.lo = nonBoostedPState;
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200697 wrmsr(PS_CTL_REG, msr);
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000698
Timothy Pearson730a0432015-10-16 13:51:51 -0500699 if (is_fam15h()) {
700 /* Do not wait for the first (even) set of cores to transition on Family 15h systems */
701 if ((cpuid_ebx(0x00000001) & 0x01000000))
702 skip_wait = 0;
703 else
704 skip_wait = 1;
705 } else {
706 skip_wait = 0;
707 }
708
709 if (!skip_wait) {
710 /* Wait for core to transition to P0 */
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200711 waitCurrentPstate(nonBoostedPState);
Timothy Pearson730a0432015-10-16 13:51:51 -0500712 }
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000713}
714
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000715static void UpdateSinglePlaneNbVid(void)
716{
717 u32 nbVid, cpuVid;
718 u8 i;
719 msr_t msr;
720
721 /* copy higher voltage (lower VID) of NBVID & CPUVID to both */
722 for (i = 0; i < 5; i++) {
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200723 msr = rdmsr(PSTATE_0_MSR + i);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000724 nbVid = (msr.lo & PS_CPU_VID_M_ON) >> PS_CPU_VID_SHFT;
725 cpuVid = (msr.lo & PS_NB_VID_M_ON) >> PS_NB_VID_SHFT;
726
727 if (nbVid != cpuVid) {
728 if (nbVid > cpuVid)
729 nbVid = cpuVid;
730
731 msr.lo = msr.lo & PS_BOTH_VID_OFF;
732 msr.lo = msr.lo | (u32) ((nbVid) << PS_NB_VID_SHFT);
733 msr.lo = msr.lo | (u32) ((nbVid) << PS_CPU_VID_SHFT);
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200734 wrmsr(PSTATE_0_MSR + i, msr);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000735 }
736 }
737}
738
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000739static void fixPsNbVidBeforeWR(u32 newNbVid, u32 coreid, u32 dev, u8 pviMode)
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600740{
741 msr_t msr;
742 u8 startup_pstate;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000743
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600744 /* This function sets NbVid before the warm reset.
745 * Get StartupPstate from MSRC001_0071.
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000746 * Read Pstate register pointed by [StartupPstate].
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600747 * and copy its content to P0 and P1 registers.
748 * Copy newNbVid to P0[NbVid].
749 * transition to P1 on all cores,
750 * then transition to P0 on core 0.
751 * Wait for MSRC001_0063[CurPstate] = 000b on core 0.
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200752 * see BKDG rev 3.48 2.4.2.9.1 BIOS NB COF and VID Configuration
753 * for SVI and Single-Plane PVI Systems
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600754 */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000755
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200756 msr = rdmsr(MSR_COFVID_STS);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000757 startup_pstate = (msr.hi >> (32 - 32)) & 0x07;
758
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000759 /* Copy startup pstate to P1 and P0 MSRs. Set the maxvid for
760 * this node in P0. Then transition to P1 for corex and P0
761 * for core0. These setting will be cleared by the warm reset
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000762 */
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200763 msr = rdmsr(PSTATE_0_MSR + startup_pstate);
764 wrmsr(PSTATE_1_MSR, msr);
765 wrmsr(PSTATE_0_MSR, msr);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000766
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200767 /* missing step 2 from BDKG , F3xDC[PstateMaxVal] =
768 * max(1,F3xDC[PstateMaxVal] ) because it would take
769 * synchronization between cores and we don't think
770 * PstatMaxVal is going to be 0 on cold reset anyway ?
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000771 */
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200772 if (!(pci_read_config32(dev, 0xdc) & (~PS_MAX_VAL_MASK))) {
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600773 printk(BIOS_ERR,"F3xDC[PstateMaxVal] is zero. Northbridge voltage setting will fail. fixPsNbVidBeforeWR in fidvid.c needs fixing. See AMD # 31116 rev 3.48 BKDG 2.4.2.9.1\n");
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000774 };
775
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000776 msr.lo &= ~0xFE000000; // clear nbvid
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000777 msr.lo |= (newNbVid << 25);
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200778 wrmsr(PSTATE_0_MSR, msr);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000779
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000780 if (pviMode) { /* single plane*/
781 UpdateSinglePlaneNbVid();
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200782 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000783
784 // Transition to P1 for all APs and P0 for core0.
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200785 set_pstate(1);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000786
787 if (coreid == 0) {
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200788 set_pstate(0);
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600789 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000790
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000791 /* missing step 7 (restore PstateMax to 0 if needed) because
792 * we skipped step 2
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000793 */
794
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000795}
796
Xavi Drudis Ferranf7ef4212011-02-27 23:58:34 +0000797static u32 needs_NB_COF_VID_update(void)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000798{
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000799 u8 nb_cof_vid_update;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000800 u8 nodes;
801 u8 i;
802
Timothy Pearson730a0432015-10-16 13:51:51 -0500803 if (is_fam15h())
804 return 0;
805
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000806 /* If any node has nb_cof_vid_update set all nodes need an update. */
807 nodes = get_nodes();
808 nb_cof_vid_update = 0;
809 for (i = 0; i < nodes; i++) {
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200810 uint64_t cpuRev = mctGetLogicalCPUID(i);
811 u32 nbCofVidUpdateDefined = (cpuRev & (AMD_FAM10_LT_D));
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000812 if (nbCofVidUpdateDefined
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200813 && (pci_read_config32(NODE_PCI(i, 3), 0x1FC)
814 & NB_COF_VID_UPDATE_MASK)) {
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000815 nb_cof_vid_update = 1;
816 break;
817 }
818 }
Xavi Drudis Ferranf7ef4212011-02-27 23:58:34 +0000819 return nb_cof_vid_update;
820}
821
Xavi Drudis Ferran1f4fffb2011-02-28 00:00:51 +0000822static u32 init_fidvid_core(u32 nodeid, u32 coreid)
Xavi Drudis Ferranf7ef4212011-02-27 23:58:34 +0000823{
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200824 pci_devfn_t dev;
Xavi Drudis Ferranf7ef4212011-02-27 23:58:34 +0000825 u32 vid_max;
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000826 u32 fid_max = 0;
Xavi Drudis Ferranf7ef4212011-02-27 23:58:34 +0000827 u8 nb_cof_vid_update = needs_NB_COF_VID_update();
828 u8 pvimode;
829 u32 reg1fc;
Xavi Drudis Ferranf7ef4212011-02-27 23:58:34 +0000830
831 /* Steps 1-6 of BIOS NB COF and VID Configuration
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000832 * for SVI and Single-Plane PVI Systems. BKDG 2.4.2.9 #31116 rev 3.48
Xavi Drudis Ferranf7ef4212011-02-27 23:58:34 +0000833 */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000834 dev = NODE_PCI(nodeid, 3);
Timothy Pearson730a0432015-10-16 13:51:51 -0500835 if (is_fam15h())
836 pvimode = 0;
837 else
838 pvimode = pci_read_config32(dev, PW_CTL_MISC) & PVI_MODE;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000839 reg1fc = pci_read_config32(dev, 0x1FC);
840
841 if (nb_cof_vid_update) {
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200842 vid_max = (reg1fc & SINGLE_PLANE_NB_VID_MASK ) >> SINGLE_PLANE_NB_VID_SHIFT;
843 fid_max = (reg1fc & SINGLE_PLANE_NB_FID_MASK ) >> SINGLE_PLANE_NB_FID_SHIFT;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000844
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200845 if (!pvimode) { /* SVI, dual power plane */
846 vid_max = vid_max - ((reg1fc & DUAL_PLANE_NB_VID_OFF_MASK ) >> DUAL_PLANE_NB_VID_SHIFT );
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000847 fid_max = fid_max + ((reg1fc & DUAL_PLANE_NB_FID_OFF_MASK ) >> DUAL_PLANE_NB_FID_SHIFT );
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000848 }
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000849 /* write newNbVid to P-state Reg's NbVid always if NbVidUpdatedAll=1 */
Timothy Pearson730a0432015-10-16 13:51:51 -0500850 fixPsNbVidBeforeWR(vid_max, coreid, dev, pvimode);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000851
852 /* fid setup is handled by the BSP at the end. */
853
854 } else { /* ! nb_cof_vid_update */
855 /* Use max values */
856 if (pvimode)
857 UpdateSinglePlaneNbVid();
858 }
859
Xavi Drudis Ferran1f4fffb2011-02-28 00:00:51 +0000860 return ((nb_cof_vid_update << 16) | (fid_max << 8));
861
862}
863
Xavi Drudis Ferran6bdc83b2011-02-28 03:56:52 +0000864static void init_fidvid_ap(u32 apicid, u32 nodeid, u32 coreid)
Xavi Drudis Ferran1f4fffb2011-02-28 00:00:51 +0000865{
866 u32 send;
867
868 printk(BIOS_DEBUG, "FIDVID on AP: %02x\n", apicid);
869
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200870 send = init_fidvid_core(nodeid, coreid);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000871 send |= (apicid << 24); // ap apicid
872
873 // Send signal to BSP about this AP max fid
874 // This also indicates this AP is ready for warm reset (if required).
875 lapic_write(LAPIC_MSG_REG, send | F10_APSTATE_RESET);
876}
877
878static u32 calc_common_fid(u32 fid_packed, u32 fid_packed_new)
879{
880 u32 fidmax;
881 u32 fidmax_new;
882
883 fidmax = (fid_packed >> 8) & 0xFF;
884
885 fidmax_new = (fid_packed_new >> 8) & 0xFF;
886
887 if (fidmax > fidmax_new) {
888 fidmax = fidmax_new;
889 }
890
891 fid_packed &= 0xFF << 16;
892 fid_packed |= (fidmax << 8);
893 fid_packed |= fid_packed_new & (0xFF << 16); // set nb_cof_vid_update
894
895 return fid_packed;
896}
897
898static void init_fidvid_bsp_stage1(u32 ap_apicid, void *gp)
899{
900 u32 readback = 0;
901 u32 timeout = 1;
902
903 struct fidvid_st *fvp = gp;
904 int loop;
905
906 print_debug_fv("Wait for AP stage 1: ap_apicid = ", ap_apicid);
907
908 loop = 100000;
909 while (--loop > 0) {
910 if (lapic_remote_read(ap_apicid, LAPIC_MSG_REG, &readback) != 0)
911 continue;
Timothy Pearson730a0432015-10-16 13:51:51 -0500912 if (((readback & 0x3f) == F10_APSTATE_RESET)
913 || (is_fam15h() && ((readback & 0x3f) == F10_APSTATE_ASLEEP))) {
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000914 timeout = 0;
915 break; /* target ap is in stage 1 */
916 }
917 }
918
919 if (timeout) {
920 printk(BIOS_DEBUG, "%s: timed out reading from ap %02x\n",
921 __func__, ap_apicid);
922 return;
923 }
924
925 print_debug_fv("\treadback = ", readback);
926
927 fvp->common_fid = calc_common_fid(fvp->common_fid, readback);
928
929 print_debug_fv("\tcommon_fid(packed) = ", fvp->common_fid);
930
931}
932
Xavi Drudis Ferranc3132102011-02-28 03:49:28 +0000933static void fixPsNbVidAfterWR(u32 newNbVid, u8 NbVidUpdatedAll,u8 pviMode)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000934{
935 msr_t msr;
936 u8 i;
937 u8 StartupPstate;
938
Xavi Drudis Ferran26f97d22011-02-28 03:08:06 +0000939 /* BKDG 2.4.2.9.1 11-12
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200940 * This function copies newNbVid to NbVid bits in P-state
Xavi Drudis Ferran26f97d22011-02-28 03:08:06 +0000941 * Registers[4:0] if its NbDid bit=0, and IddValue!=0 in case of
942 * NbVidUpdatedAll =0 or copies newNbVid to NbVid bits in
943 * P-state Registers[4:0] if its IddValue!=0 in case of
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000944 * NbVidUpdatedAll=1. Then transition to StartPstate.
945 */
946
947 /* write newNbVid to P-state Reg's NbVid if its NbDid=0 */
948 for (i = 0; i < 5; i++) {
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200949 msr = rdmsr(PSTATE_0_MSR + i);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000950 /* NbDid (bit 22 of P-state Reg) == 0 or NbVidUpdatedAll = 1 */
Xavi Drudis Ferranc3132102011-02-28 03:49:28 +0000951 if ( (msr.hi & PS_IDD_VALUE_MASK)
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200952 && (msr.hi & PS_EN_MASK)
953 &&(((msr.lo & PS_NB_DID_MASK) == 0) || NbVidUpdatedAll)) {
Xavi Drudis Ferran26f97d22011-02-28 03:08:06 +0000954 msr.lo &= PS_NB_VID_M_OFF;
955 msr.lo |= (newNbVid & 0x7F) << PS_NB_VID_SHFT;
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200956 wrmsr(PSTATE_0_MSR + i, msr);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000957 }
958 }
959
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200960 /* Not documented. Would overwrite Nb_Vids just copied
961 * should we just update cpu_vid or nothing at all ?
Xavi Drudis Ferran26f97d22011-02-28 03:08:06 +0000962 */
963 if (pviMode) { //single plane
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200964 UpdateSinglePlaneNbVid();
Xavi Drudis Ferran26f97d22011-02-28 03:08:06 +0000965 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000966 /* For each core in the system, transition all cores to StartupPstate */
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200967 msr = rdmsr(MSR_COFVID_STS);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000968 StartupPstate = msr.hi & 0x07;
Xavi Drudis Ferranc3132102011-02-28 03:49:28 +0000969
Xavi Drudis Ferran26f97d22011-02-28 03:08:06 +0000970 /* Set and wait for StartupPstate to set. */
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200971 set_pstate(StartupPstate);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000972
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000973}
974
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000975static void finalPstateChange(void)
976{
Martin Roth4c3ab732013-07-08 16:23:54 -0600977 /* Enable P0 on all cores for best performance.
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000978 * Linux can slow them down later if need be.
979 * It is safe since they will be in C1 halt
980 * most of the time anyway.
981 */
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000982 set_pstate(0);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000983}
984
Damien Zammit75a3d1f2016-11-28 00:29:10 +1100985void init_fidvid_stage2(u32 apicid, u32 nodeid)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000986{
987 msr_t msr;
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200988 pci_devfn_t dev;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000989 u32 reg1fc;
990 u32 dtemp;
991 u32 nbvid;
Xavi Drudis Ferranf7ef4212011-02-27 23:58:34 +0000992 u8 nb_cof_vid_update = needs_NB_COF_VID_update();
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000993 u8 NbVidUpdateAll;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000994 u8 pvimode;
995
996 /* After warm reset finish the fid/vid setup for all cores. */
997
998 /* If any node has nb_cof_vid_update set all nodes need an update. */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000999
1000 dev = NODE_PCI(nodeid, 3);
Timothy Pearson730a0432015-10-16 13:51:51 -05001001 if (is_fam15h())
1002 pvimode = 0;
1003 else
1004 pvimode = (pci_read_config32(dev, 0xA0) >> 8) & 1;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001005 reg1fc = pci_read_config32(dev, 0x1FC);
1006 nbvid = (reg1fc >> 7) & 0x7F;
1007 NbVidUpdateAll = (reg1fc >> 1) & 1;
1008
1009 if (nb_cof_vid_update) {
Xavi Drudis Ferran26f97d22011-02-28 03:08:06 +00001010 if (!pvimode) { /* SVI */
1011 nbvid = nbvid - ((reg1fc >> 17) & 0x1F);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001012 }
Xavi Drudis Ferran26f97d22011-02-28 03:08:06 +00001013 /* write newNbVid to P-state Reg's NbVid if its NbDid=0 */
1014 fixPsNbVidAfterWR(nbvid, NbVidUpdateAll,pvimode);
Martin Rothe5f2d4c2017-07-23 16:07:31 -06001015 } else { /* !nb_cof_vid_update */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001016 if (pvimode)
1017 UpdateSinglePlaneNbVid();
1018 }
1019 dtemp = pci_read_config32(dev, 0xA0);
1020 dtemp &= PLLLOCK_OFF;
1021 dtemp |= PLLLOCK_DFT_L;
1022 pci_write_config32(dev, 0xA0, dtemp);
1023
Elyes HAOUAS2765a892016-09-01 19:44:56 +02001024 dualPlaneOnly(dev);
1025 applyBoostFIDOffset(dev, nodeid);
1026 enableNbPState1(dev);
Xavi Drudis Ferran5bcedee2011-02-28 03:25:07 +00001027
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001028 finalPstateChange();
1029
Timothy Pearson730a0432015-10-16 13:51:51 -05001030 if (!is_fam15h()) {
1031 /* Set TSC to tick at the P0 ndfid rate */
Elyes HAOUAS400ce552018-10-12 10:54:30 +02001032 msr = rdmsr(HWCR_MSR);
Timothy Pearson730a0432015-10-16 13:51:51 -05001033 msr.lo |= 1 << 24;
Elyes HAOUAS400ce552018-10-12 10:54:30 +02001034 wrmsr(HWCR_MSR, msr);
Timothy Pearson730a0432015-10-16 13:51:51 -05001035 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001036}
1037
1038
Martin Roth5f46af62017-06-24 13:24:26 -06001039#if IS_ENABLED(CONFIG_SET_FIDVID_STORE_AP_APICID_AT_FIRST)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001040struct ap_apicid_st {
1041 u32 num;
1042 // it could use 256 bytes for 64 node quad core system
1043 u8 apicid[NODE_NUMS * 4];
1044};
1045
1046static void store_ap_apicid(unsigned ap_apicid, void *gp)
1047{
1048 struct ap_apicid_st *p = gp;
1049
1050 p->apicid[p->num++] = ap_apicid;
1051
1052}
1053#endif
1054
1055
Damien Zammit75a3d1f2016-11-28 00:29:10 +11001056int init_fidvid_bsp(u32 bsp_apicid, u32 nodes)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001057{
Martin Roth5f46af62017-06-24 13:24:26 -06001058#if IS_ENABLED(CONFIG_SET_FIDVID_STORE_AP_APICID_AT_FIRST)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001059 struct ap_apicid_st ap_apicidx;
1060 u32 i;
1061#endif
1062 struct fidvid_st fv;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001063
1064 printk(BIOS_DEBUG, "FIDVID on BSP, APIC_id: %02x\n", bsp_apicid);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001065
1066 /* Steps 1-6 of BIOS NB COF and VID Configuration
1067 * for SVI and Single-Plane PVI Systems.
1068 */
Timothy Pearson730a0432015-10-16 13:51:51 -05001069 fv.common_fid = init_fidvid_core(0, 0);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001070
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001071 print_debug_fv("BSP fid = ", fv.common_fid);
1072
Martin Roth5f46af62017-06-24 13:24:26 -06001073#if IS_ENABLED(CONFIG_SET_FIDVID_STORE_AP_APICID_AT_FIRST) && \
1074 !IS_ENABLED(CONFIG_SET_FIDVID_CORE0_ONLY)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001075 /* For all APs (We know the APIC ID of all APs even when the APIC ID
1076 is lifted) remote read from AP LAPIC_MSG_REG about max fid.
1077 Then calculate the common max fid that can be used for all
1078 APs and BSP */
1079 ap_apicidx.num = 0;
1080
Timothy Pearson0122afb2015-07-30 14:07:15 -05001081 for_each_ap(bsp_apicid, CONFIG_SET_FIDVID_CORE_RANGE, -1, store_ap_apicid, &ap_apicidx);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001082
1083 for (i = 0; i < ap_apicidx.num; i++) {
1084 init_fidvid_bsp_stage1(ap_apicidx.apicid[i], &fv);
1085 }
1086#else
Timothy Pearson0122afb2015-07-30 14:07:15 -05001087 for_each_ap(bsp_apicid, CONFIG_SET_FIDVID_CORE0_ONLY, -1, init_fidvid_bsp_stage1, &fv);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001088#endif
1089
1090 print_debug_fv("common_fid = ", fv.common_fid);
1091
1092 if (fv.common_fid & (1 << 16)) { /* check nb_cof_vid_update */
1093
1094 // Enable the common fid and other settings.
1095 enable_fid_change((fv.common_fid >> 8) & 0x1F);
1096
1097 // nbfid change need warm reset, so reset at first
1098 return 1;
1099 }
1100
1101 return 0; // No FID/VID changes. Don't reset
1102}