blob: e4bb9a3e08062c74885837b06fc3576d2de9786b [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
Damien Zammit75a3d1f2016-11-28 00:29:10 +110092#include <inttypes.h>
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000093#include <northbridge/amd/amdht/AsPsDefs.h>
94
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000095static inline void print_debug_fv(const char *str, u32 val)
96{
Martin Roth5f46af62017-06-24 13:24:26 -060097#if IS_ENABLED(CONFIG_SET_FIDVID_DEBUG)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000098 printk(BIOS_DEBUG, "%s%x\n", str, val);
99#endif
100}
101
102static inline void print_debug_fv_8(const char *str, u8 val)
103{
Martin Roth5f46af62017-06-24 13:24:26 -0600104#if IS_ENABLED(CONFIG_SET_FIDVID_DEBUG)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000105 printk(BIOS_DEBUG, "%s%02x\n", str, val);
106#endif
107}
108
109static inline void print_debug_fv_64(const char *str, u32 val, u32 val2)
110{
Martin Roth5f46af62017-06-24 13:24:26 -0600111#if IS_ENABLED(CONFIG_SET_FIDVID_DEBUG)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000112 printk(BIOS_DEBUG, "%s%x%x\n", str, val, val2);
113#endif
114}
115
116struct fidvid_st {
117 u32 common_fid;
118};
119
120static void enable_fid_change(u8 fid)
121{
122 u32 dword;
123 u32 nodes;
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200124 pci_devfn_t dev;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000125 int i;
126
127 nodes = get_nodes();
128
129 for (i = 0; i < nodes; i++) {
130 dev = NODE_PCI(i, 3);
131 dword = pci_read_config32(dev, 0xd4);
132 dword &= ~0x1F;
133 dword |= (u32) fid & 0x1F;
134 dword |= 1 << 5; // enable
135 pci_write_config32(dev, 0xd4, dword);
Elyes HAOUAS7c8d74c2016-08-23 21:41:43 +0200136 printk(BIOS_DEBUG, "FID Change Node:%02x, F3xD4: %08x\n", i,
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000137 dword);
138 }
139}
Xavi Drudis Ferran5bcedee2011-02-28 03:25:07 +0000140
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200141static void applyBoostFIDOffset(pci_devfn_t dev, uint32_t nodeid)
142{
Timothy Pearson730a0432015-10-16 13:51:51 -0500143 // BKDG 2.4.2.8
144 // Fam10h revision E only, but E is apparently not supported yet, therefore untested
145 if ((cpuid_edx(0x80000007) & CPB_MASK)
146 && ((cpuid_ecx(0x80000008) & NC_MASK) == 5) ) {
147 u32 core = get_node_core_id_x().coreid;
148 u32 asymetricBoostThisCore = ((pci_read_config32(dev, 0x10C) >> (core*2))) & 3;
149 msr_t msr = rdmsr(PS_REG_BASE);
150 u32 cpuFid = msr.lo & PS_CPU_FID_MASK;
151 cpuFid = cpuFid + asymetricBoostThisCore;
152 msr.lo &= ~PS_CPU_FID_MASK;
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200153 msr.lo |= cpuFid;
Timothy Pearson730a0432015-10-16 13:51:51 -0500154 wrmsr(PS_REG_BASE , msr);
155 } else if (is_fam15h()) {
156 uint32_t dword = pci_read_config32(NODE_PCI(nodeid, 4), 0x15c);
157 uint8_t boost_count = (dword >> 2) & 0x7;
158 if (boost_count > 0) {
159 /* Enable boost */
160 dword &= ~0x3;
161 dword |= 0x1;
162 pci_write_config32(NODE_PCI(nodeid, 4), 0x15c, dword);
163 }
164 }
Xavi Drudis Ferran5bcedee2011-02-28 03:25:07 +0000165}
166
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200167static void enableNbPState1(pci_devfn_t dev)
168{
Timothy Pearson83abd812015-06-08 19:35:06 -0500169 uint64_t cpuRev = mctGetLogicalCPUID(0xFF);
170 if (cpuRev & AMD_FAM10_C3) {
171 u32 nbPState = (pci_read_config32(dev, 0x1F0) & NB_PSTATE_MASK);
172 if ( nbPState){
173 u32 nbVid1 = (pci_read_config32(dev, 0x1F4) & NB_VID1_MASK) >> NB_VID1_SHIFT;
174 u32 i;
175 for (i = nbPState; i < NM_PS_REG; i++) {
176 msr_t msr = rdmsr(PS_REG_BASE + i);
177 if (msr.hi & PS_EN_MASK ) {
178 msr.hi |= NB_DID_M_ON;
179 msr.lo &= NB_VID_MASK_OFF;
180 msr.lo |= ( nbVid1 << NB_VID_POS);
181 wrmsr(PS_REG_BASE + i, msr);
182 }
183 }
184 }
185 }
Xavi Drudis Ferrane80ce0a2011-02-28 03:12:00 +0000186}
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000187
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200188static u8 setPStateMaxVal(pci_devfn_t dev)
189{
Timothy Pearson83abd812015-06-08 19:35:06 -0500190 u8 i, maxpstate=0;
191 for (i = 0; i < NM_PS_REG; i++) {
192 msr_t msr = rdmsr(PS_REG_BASE + i);
193 if (msr.hi & PS_IDD_VALUE_MASK) {
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200194 msr.hi |= PS_EN_MASK;
Timothy Pearson83abd812015-06-08 19:35:06 -0500195 wrmsr(PS_REG_BASE + i, msr);
196 }
197 if (msr.hi & PS_EN_MASK) {
198 maxpstate = i;
199 }
200 }
201 //FIXME: CPTC2 and HTC_REG should get max per node, not per core ?
202 u32 reg = pci_read_config32(dev, CPTC2);
203 reg &= PS_MAX_VAL_MASK;
204 reg |= (maxpstate << PS_MAX_VAL_POS);
205 pci_write_config32(dev, CPTC2,reg);
206 return maxpstate;
Xavi Drudis Ferrance623502011-02-28 03:19:17 +0000207}
208
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200209static void dualPlaneOnly(pci_devfn_t dev)
210{
Timothy Pearson83abd812015-06-08 19:35:06 -0500211 // BKDG 2.4.2.7
Xavi Drudis Ferrance623502011-02-28 03:19:17 +0000212
Timothy Pearson83abd812015-06-08 19:35:06 -0500213 uint64_t cpuRev = mctGetLogicalCPUID(0xFF);
214 if ((mctGetProcessorPackageType() == AMD_PKGTYPE_AM3_2r2)
215 && (cpuRev & (AMD_DR_Cx | AMD_DR_Ex))) {
216 if ((pci_read_config32(dev, 0x1FC) & DUAL_PLANE_ONLY_MASK)
217 && (pci_read_config32(dev, 0xA0) & PVI_MODE)) {
218 if (cpuid_edx(0x80000007) & CPB_MASK) {
219 // revision E only, but E is apparently not supported yet, therefore untested
220 msr_t minPstate = rdmsr(0xC0010065);
221 wrmsr(0xC0010065, rdmsr(0xC0010068));
222 wrmsr(0xC0010068, minPstate);
223 } else {
224 msr_t msr;
225 msr.lo=0; msr.hi=0;
226 wrmsr(0xC0010064, rdmsr(0xC0010068) );
227 wrmsr(0xC0010068, msr);
228 }
Xavi Drudis Ferranc3132102011-02-28 03:49:28 +0000229
Timothy Pearson83abd812015-06-08 19:35:06 -0500230 //FIXME: CPTC2 and HTC_REG should get max per node, not per core ?
231 u8 maxpstate = setPStateMaxVal(dev);
Xavi Drudis Ferrance623502011-02-28 03:19:17 +0000232
Timothy Pearson83abd812015-06-08 19:35:06 -0500233 u32 reg = pci_read_config32(dev, HTC_REG);
234 reg &= HTC_PS_LMT_MASK;
235 reg |= (maxpstate << PS_LIMIT_POS);
236 pci_write_config32(dev, HTC_REG,reg);
237 }
238 }
Xavi Drudis Ferrance623502011-02-28 03:19:17 +0000239}
240
Xavi Drudis Ferranc3132102011-02-28 03:49:28 +0000241static int vidTo100uV(u8 vid)
Timothy Pearson83abd812015-06-08 19:35:06 -0500242{
243 // returns voltage corresponding to vid in tenths of mV, i.e. hundreds of uV
244 // BKDG #31116 rev 3.48 2.4.1.6
245 int voltage;
246 if (vid >= 0x7c) {
247 voltage = 0;
248 } else {
249 voltage = (15500 - (125*vid));
250 }
251 return voltage;
Xavi Drudis Ferran82b241a2011-02-28 03:32:23 +0000252}
253
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200254static void setVSRamp(pci_devfn_t dev)
255{
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000256 /* BKDG r31116 2010-04-22 2.4.1.7 step b F3xD8[VSRampTime]
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200257 * If this field accepts 8 values between 10 and 500 us why
258 * does page 324 say "BIOS should set this field to 001b."
259 * (20 us) ?
260 * Shouldn't it depend on the voltage regulators, mainboard
261 * or something ?
262 */
263 u32 dword;
Xavi Drudis Ferrand7294592011-02-27 23:42:58 +0000264 dword = pci_read_config32(dev, 0xd8);
265 dword &= VSRAMP_MASK;
266 dword |= VSRAMP_VALUE;
267 pci_write_config32(dev, 0xd8, dword);
268}
269
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200270static void recalculateVsSlamTimeSettingOnCorePre(pci_devfn_t dev)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000271{
272 u8 pviModeFlag;
273 u8 highVoltageVid, lowVoltageVid, bValue;
274 u16 minimumSlamTime;
275 u16 vSlamTimes[7] = { 1000, 2000, 3000, 4000, 6000, 10000, 20000 }; /* Reg settings scaled by 100 */
276 u32 dtemp;
277 msr_t msr;
278
279 /* This function calculates the VsSlamTime using the range of possible
280 * voltages instead of a hardcoded 200us.
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200281 * Note: his function is called only from prep_fid_change,
282 * and that from init_cpus.c finalize_node_setup()
283 * (after set AMD MSRs and init ht )
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000284 */
285
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200286 /* BKDG r31116 2010-04-22 2.4.1.7 step b F3xD8[VSSlamTime] */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000287 /* Calculate Slam Time
Xavi Drudis Ferran82b241a2011-02-28 03:32:23 +0000288 * Vslam = (mobileCPU?0.2:0.4)us/mV * (Vp0 - (lowest out of Vpmin or Valt)) mV
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000289 * In our case, we will scale the values by 100 to avoid
290 * decimals.
291 */
292
293 /* Determine if this is a PVI or SVI system */
Timothy Pearson730a0432015-10-16 13:51:51 -0500294 if (is_fam15h()) {
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000295 pviModeFlag = 0;
Timothy Pearson730a0432015-10-16 13:51:51 -0500296 } else {
297 dtemp = pci_read_config32(dev, 0xa0);
298
299 if (dtemp & PVI_MODE)
300 pviModeFlag = 1;
301 else
302 pviModeFlag = 0;
303 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000304
305 /* Get P0's voltage */
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200306 /* MSRC001_00[68:64] are not programmed yet when called from
Xavi Drudis Ferran82b241a2011-02-28 03:32:23 +0000307 prep_fid_change, one might use F4x1[F0:E0] instead, but
308 theoretically MSRC001_00[68:64] are equal to them after
309 reset. */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000310 msr = rdmsr(0xC0010064);
311 highVoltageVid = (u8) ((msr.lo >> PS_CPU_VID_SHFT) & 0x7F);
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200312 if (!(msr.hi & 0x80000000)) {
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600313 printk(BIOS_ERR,"P-state info in MSRC001_0064 is invalid !!!\n");
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200314 highVoltageVid = (u8) ((pci_read_config32(dev, 0x1E0)
315 >> PS_CPU_VID_SHFT) & 0x7F);
Xavi Drudis Ferran82b241a2011-02-28 03:32:23 +0000316 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000317
318 /* If SVI, we only care about CPU VID.
319 * If PVI, determine the higher voltage b/t NB and CPU
320 */
321 if (pviModeFlag) {
322 bValue = (u8) ((msr.lo >> PS_NB_VID_SHFT) & 0x7F);
323 if (highVoltageVid > bValue)
324 highVoltageVid = bValue;
325 }
326
Xavi Drudis Ferran82b241a2011-02-28 03:32:23 +0000327 /* Get PSmax's index */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000328 msr = rdmsr(0xC0010061);
Xavi Drudis Ferran82b241a2011-02-28 03:32:23 +0000329 bValue = (u8) ((msr.lo >> PS_MAX_VAL_SHFT) & BIT_MASK_3);
Xavi Drudis Ferranc3132102011-02-28 03:49:28 +0000330
Xavi Drudis Ferran82b241a2011-02-28 03:32:23 +0000331 /* Get PSmax's VID */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000332 msr = rdmsr(0xC0010064 + bValue);
333 lowVoltageVid = (u8) ((msr.lo >> PS_CPU_VID_SHFT) & 0x7F);
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200334 if (!(msr.hi & 0x80000000)) {
Xavi Drudis Ferran82b241a2011-02-28 03:32:23 +0000335 printk(BIOS_ERR,"P-state info in MSR%8x is invalid !!!\n",0xC0010064 + bValue);
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200336 lowVoltageVid = (u8) ((pci_read_config32(dev, 0x1E0+(bValue*4))
337 >> PS_CPU_VID_SHFT) & 0x7F);
Xavi Drudis Ferran82b241a2011-02-28 03:32:23 +0000338 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000339
340 /* If SVI, we only care about CPU VID.
341 * If PVI, determine the higher voltage b/t NB and CPU
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200342 * BKDG 2.4.1.7 (a)
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600343 */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000344 if (pviModeFlag) {
345 bValue = (u8) ((msr.lo >> PS_NB_VID_SHFT) & 0x7F);
346 if (lowVoltageVid > bValue)
347 lowVoltageVid = bValue;
348 }
349
350 /* Get AltVID */
Timothy Pearson83abd812015-06-08 19:35:06 -0500351 dtemp = pci_read_config32(dev, 0xdc);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000352 bValue = (u8) (dtemp & BIT_MASK_7);
353
354 /* Use the VID with the lowest voltage (higher VID) */
355 if (lowVoltageVid < bValue)
356 lowVoltageVid = bValue;
357
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200358 u8 mobileFlag = get_platform_type() & AMD_PTYPE_MOB;
Xavi Drudis Ferran82b241a2011-02-28 03:32:23 +0000359 minimumSlamTime = (mobileFlag?2:4) * (vidTo100uV(highVoltageVid) - vidTo100uV(lowVoltageVid)); /* * 0.01 us */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000360
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000361
362 /* Now round up to nearest register setting.
363 * Note that if we don't find a value, we
364 * will fall through to a value of 7
365 */
366 for (bValue = 0; bValue < 7; bValue++) {
367 if (minimumSlamTime <= vSlamTimes[bValue])
368 break;
369 }
370
371 /* Apply the value */
372 dtemp = pci_read_config32(dev, 0xD8);
373 dtemp &= VSSLAM_MASK;
374 dtemp |= bValue;
375 pci_write_config32(dev, 0xd8, dtemp);
376}
377
Timothy Pearson5173bb72015-08-02 21:31:48 -0500378static u32 nb_clk_did(uint8_t node, uint64_t cpuRev, uint8_t procPkg) {
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200379 uint8_t link0isGen3 = 0;
380 uint8_t offset;
381 if (AMD_CpuFindCapability(node, 0, &offset)) {
Timothy Pearsonf8549e82015-09-07 22:26:55 -0500382 link0isGen3 = (AMD_checkLinkType(node, offset) & HTPHY_LINKTYPE_HT3 );
Xavi Drudis Ferranadb23a52011-02-28 00:10:37 +0000383 }
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200384 /* FIXME: NB_CLKDID should be 101b for AMD_DA_C2 in package
385 S1g3 in link Gen3 mode, but I don't know how to tell
386 package S1g3 from S1g4 */
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000387 if ((cpuRev & AMD_DA_C2) && (procPkg & AMD_PKGTYPE_S1gX)
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200388 && link0isGen3) {
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200389 return 5; /* divide clk by 128*/
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200390 } else {
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200391 return 4; /* divide clk by 16 */
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200392 }
Xavi Drudis Ferranadb23a52011-02-28 00:10:37 +0000393}
394
395
396static u32 power_up_down(int node, u8 procPkg) {
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600397 uint32_t dword=0;
398 /* from CPU rev guide #41322 rev 3.74 June 2010 Table 26 */
399 u8 singleLinkFlag = ((procPkg == AMD_PKGTYPE_AM3_2r2)
400 || (procPkg == AMD_PKGTYPE_S1gX)
401 || (procPkg == AMD_PKGTYPE_ASB2));
Xavi Drudis Ferranadb23a52011-02-28 00:10:37 +0000402
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600403 if (singleLinkFlag) {
404 /*
405 * PowerStepUp=01000b - 50nS
406 * PowerStepDown=01000b - 50ns
Xavi Drudis Ferrana5cbd252011-02-27 23:45:34 +0000407 */
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600408 dword |= PW_STP_UP50 | PW_STP_DN50;
409 } else {
410 uint32_t dispRefModeEn = (pci_read_config32(NODE_PCI(node,0),0x68) >> 24) & 1;
411 uint32_t isocEn = 0;
412 int j;
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200413 for (j=0; (j<4) && (!isocEn); j++ ) {
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600414 u8 offset;
415 if (AMD_CpuFindCapability(node, j, &offset)) {
416 isocEn = (pci_read_config32(NODE_PCI(node,0),offset+4) >>12) & 1;
417 }
Xavi Drudis Ferrana5cbd252011-02-27 23:45:34 +0000418 }
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600419
420 if (is_fam15h()) {
421 /* Family 15h always uses 100ns for multilink processors */
422 dword |= PW_STP_UP100 | PW_STP_DN100;
423 } else if (dispRefModeEn || isocEn) {
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200424 dword |= PW_STP_UP50 | PW_STP_DN50;
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600425 } else {
426 /* get number of cores for PowerStepUp & PowerStepDown in server
427 * 1 core - 400nS - 0000b
428 * 2 cores - 200nS - 0010b
429 * 3 cores - 133nS -> 100nS - 0011b
430 * 4 cores - 100nS - 0011b
431 */
432 switch (get_core_num_in_bsp(node)) {
433 case 0:
434 dword |= PW_STP_UP400 | PW_STP_DN400;
435 break;
436 case 1:
437 case 2:
438 dword |= PW_STP_UP200 | PW_STP_DN200;
439 break;
440 case 3:
441 dword |= PW_STP_UP100 | PW_STP_DN100;
442 break;
443 default:
444 dword |= PW_STP_UP100 | PW_STP_DN100;
445 break;
446 }
447 }
Xavi Drudis Ferrana5cbd252011-02-27 23:45:34 +0000448 }
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600449
450 return dword;
Xavi Drudis Ferrand26e5e62011-02-27 23:56:00 +0000451}
452
Timothy Pearson5173bb72015-08-02 21:31:48 -0500453static void config_clk_power_ctrl_reg0(uint8_t node, uint64_t cpuRev, uint8_t procPkg) {
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200454
455 pci_devfn_t dev = NODE_PCI(node, 3);
Xavi Drudis Ferrand26e5e62011-02-27 23:56:00 +0000456
Xavi Drudis Ferrand26e5e62011-02-27 23:56:00 +0000457 /* Program fields in Clock Power/Control register0 (F3xD4) */
458
459 /* set F3xD4 Clock Power/Timing Control 0 Register
460 * NbClkDidApplyAll=1b
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000461 * NbClkDid=100b or 101b
Xavi Drudis Ferrand26e5e62011-02-27 23:56:00 +0000462 * PowerStepUp= "platform dependent"
463 * PowerStepDown= "platform dependent"
464 * LinkPllLink=01b
Xavi Drudis Ferranadb23a52011-02-28 00:10:37 +0000465 * ClkRampHystCtl=HW default
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200466 * ClkRampHystSel=1111b
Xavi Drudis Ferrand26e5e62011-02-27 23:56:00 +0000467 */
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200468 uint32_t dword= pci_read_config32(dev, 0xd4);
Xavi Drudis Ferrand26e5e62011-02-27 23:56:00 +0000469 dword &= CPTC0_MASK;
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200470 dword |= NB_CLKDID_ALL | LNK_PLL_LOCK | CLK_RAMP_HYST_SEL_VAL;
471 dword |= (nb_clk_did(node,cpuRev,procPkg) << NB_CLKDID_SHIFT);
Xavi Drudis Ferranadb23a52011-02-28 00:10:37 +0000472
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200473 dword |= power_up_down(node, procPkg);
Xavi Drudis Ferrand26e5e62011-02-27 23:56:00 +0000474
475 pci_write_config32(dev, 0xd4, dword);
476
Xavi Drudis Ferrana5cbd252011-02-27 23:45:34 +0000477}
478
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200479static void config_power_ctrl_misc_reg(pci_devfn_t dev, uint64_t cpuRev,
480 uint8_t procPkg)
481{
Xavi Drudis Ferran9683b1d2011-02-27 23:47:57 +0000482 /* check PVI/SVI */
Timothy Pearson5173bb72015-08-02 21:31:48 -0500483 uint32_t dword = pci_read_config32(dev, 0xa0);
Xavi Drudis Ferran0e5d3e12011-02-28 00:18:43 +0000484
Timothy Pearson38629f52015-09-05 18:46:54 -0500485 /* BKDG r31116 2010-04-22 2.4.1.7 step b F3xA0[VSSlamVidMod] */
486 /* PllLockTime and PsiVidEn set in ruleset in defaults.h */
Xavi Drudis Ferran9683b1d2011-02-27 23:47:57 +0000487 if (dword & PVI_MODE) { /* PVI */
488 /* set slamVidMode to 0 for PVI */
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200489 dword &= VID_SLAM_OFF;
Xavi Drudis Ferran9683b1d2011-02-27 23:47:57 +0000490 } else { /* SVI */
491 /* set slamVidMode to 1 for SVI */
Xavi Drudis Ferran0e5d3e12011-02-28 00:18:43 +0000492 dword |= VID_SLAM_ON;
Timothy Pearson38629f52015-09-05 18:46:54 -0500493 }
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200494 /* set the rest of A0 since we're at it... */
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000495
Timothy Pearson38629f52015-09-05 18:46:54 -0500496 if (cpuRev & (AMD_DA_Cx | AMD_RB_C3 )) {
497 dword |= NB_PSTATE_FORCE_ON;
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000498 } // else should we clear it ?
Xavi Drudis Ferran0e5d3e12011-02-28 00:18:43 +0000499
500
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200501 if ((procPkg == AMD_PKGTYPE_G34) || (procPkg == AMD_PKGTYPE_C32) ) {
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200502 dword |= BP_INS_TRI_EN_ON;
Xavi Drudis Ferran9683b1d2011-02-27 23:47:57 +0000503 }
Xavi Drudis Ferran0e5d3e12011-02-28 00:18:43 +0000504
505 /* TODO: look into C1E state and F3xA0[IdleExitEn]*/
Martin Roth5f46af62017-06-24 13:24:26 -0600506 #if IS_ENABLED(CONFIG_SVI_HIGH_FREQ)
Timothy Pearson38629f52015-09-05 18:46:54 -0500507 if (cpuRev & AMD_FAM10_C3) {
508 dword |= SVI_HIGH_FREQ_ON;
509 }
510 #endif
511 pci_write_config32(dev, 0xa0, dword);
Xavi Drudis Ferran9683b1d2011-02-27 23:47:57 +0000512}
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000513
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200514static void config_nb_syn_ptr_adj(pci_devfn_t dev, uint64_t cpuRev)
515{
Xavi Drudis Ferran1d80e512011-02-27 23:50:30 +0000516 /* Note the following settings are additional from the ported
517 * function setFidVidRegs()
518 */
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200519 /* adjust FIFO between nb and core clocks to max allowed
520 values (min latency) */
Timothy Pearson5173bb72015-08-02 21:31:48 -0500521 uint32_t nbPstate = pci_read_config32(dev,0x1f0) & NB_PSTATE_MASK;
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200522 uint8_t nbSynPtrAdj;
Timothy Pearson83abd812015-06-08 19:35:06 -0500523 if ((cpuRev & (AMD_DR_Bx | AMD_DA_Cx | AMD_FAM15_ALL) )
524 || ((cpuRev & AMD_RB_C3) && (nbPstate != 0))) {
525 nbSynPtrAdj = 5;
Xavi Drudis Ferran1f93fea2011-02-28 00:24:21 +0000526 } else {
Timothy Pearson83abd812015-06-08 19:35:06 -0500527 nbSynPtrAdj = 6;
Xavi Drudis Ferran1f93fea2011-02-28 00:24:21 +0000528 }
Xavi Drudis Ferran1d80e512011-02-27 23:50:30 +0000529
Timothy Pearson5173bb72015-08-02 21:31:48 -0500530 uint32_t dword = pci_read_config32(dev, 0xdc);
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200531 dword &= ~NB_SYN_PTR_ADJ_MASK;
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000532 dword |= nbSynPtrAdj << NB_SYN_PTR_ADJ_POS;
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200533 /* NbsynPtrAdj set to 5 or 6 per BKDG (needs reset) */
Xavi Drudis Ferran1f93fea2011-02-28 00:24:21 +0000534 pci_write_config32(dev, 0xdc, dword);
Xavi Drudis Ferran1d80e512011-02-27 23:50:30 +0000535}
536
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200537static void config_acpi_pwr_state_ctrl_regs(pci_devfn_t dev, uint64_t cpuRev,
538 uint8_t procPkg)
539{
Timothy Pearson730a0432015-10-16 13:51:51 -0500540 if (is_fam15h()) {
541 /* Family 15h BKDG Rev. 3.14 D18F3x80 recommended settings */
542 pci_write_config32(dev, 0x80, 0xe20be281);
Xavi Drudis Ferran6fcc9612011-02-28 00:31:24 +0000543
Timothy Pearson730a0432015-10-16 13:51:51 -0500544 /* Family 15h BKDG Rev. 3.14 D18F3x84 recommended settings */
545 pci_write_config32(dev, 0x84, 0x01e200e2);
546 } else {
547 /* 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 -0500548 uint32_t dword;
549 uint32_t c1= 1;
Timothy Pearson730a0432015-10-16 13:51:51 -0500550 if (cpuRev & (AMD_DR_Bx)) {
551 // will coreboot ever enable cache scrubbing ?
552 // if it does, will it be enough to check the current state
553 // or should we configure for what we'll set up later ?
554 dword = pci_read_config32(dev, 0x58);
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600555 uint32_t scrubbingCache = dword &
Timothy Pearson730a0432015-10-16 13:51:51 -0500556 ( (0x1F << 16) // DCacheScrub
557 | (0x1F << 8) ); // L2Scrub
558 if (scrubbingCache) {
559 c1 = 0x80;
560 } else {
561 c1 = 0xA0;
562 }
563 } else { // rev C or later
564 // same doubt as cache scrubbing: ok to check current state ?
Timothy Pearson83abd812015-06-08 19:35:06 -0500565 dword = pci_read_config32(dev, 0xdc);
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600566 uint32_t cacheFlushOnHalt = dword & (7 << 16);
Timothy Pearson730a0432015-10-16 13:51:51 -0500567 if (!cacheFlushOnHalt) {
568 c1 = 0x80;
569 }
570 }
571 dword = (c1 << 24) | (0xE641E6);
572 pci_write_config32(dev, 0x84, dword);
Xavi Drudis Ferran6fcc9612011-02-28 00:31:24 +0000573
Timothy Pearson730a0432015-10-16 13:51:51 -0500574 /* FIXME: BKDG Table 100 says if the link is at a Gen1
575 * frequency and the chipset does not support a 10us minimum LDTSTOP
576 * assertion time, then { If ASB2 && SVI then smaf001 = F6h else
577 * smaf001=87h. } else ... I hardly know what it means or how to check
578 * it from here, so I bluntly assume it is false and code here the else,
579 * which is easier
580 */
Xavi Drudis Ferran6fcc9612011-02-28 00:31:24 +0000581
Timothy Pearson5173bb72015-08-02 21:31:48 -0500582 uint32_t smaf001 = 0xE6;
Timothy Pearson730a0432015-10-16 13:51:51 -0500583 if (cpuRev & AMD_DR_Bx ) {
584 smaf001 = 0xA6;
585 } else {
Martin Roth5f46af62017-06-24 13:24:26 -0600586 #if IS_ENABLED(CONFIG_SVI_HIGH_FREQ)
Timothy Pearson730a0432015-10-16 13:51:51 -0500587 if (cpuRev & (AMD_RB_C3 | AMD_DA_C3)) {
588 smaf001 = 0xF6;
589 }
590 #endif
591 }
Timothy Pearson5173bb72015-08-02 21:31:48 -0500592 uint32_t fidvidChange = 0;
Timothy Pearson730a0432015-10-16 13:51:51 -0500593 if (((cpuRev & AMD_DA_Cx) && (procPkg & AMD_PKGTYPE_S1gX))
594 || (cpuRev & AMD_RB_C3) ) {
595 fidvidChange=0x0B;
596 }
597 dword = (0xE6 << 24) | (fidvidChange << 16)
598 | (smaf001 << 8) | 0x81;
599 pci_write_config32(dev, 0x80, dword);
600 }
Xavi Drudis Ferran40f9b4b02011-02-27 23:53:11 +0000601}
602
Damien Zammit75a3d1f2016-11-28 00:29:10 +1100603void prep_fid_change(void)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000604{
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200605 u32 dword;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000606 u32 nodes;
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200607 pci_devfn_t dev;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000608 int i;
609
610 /* This needs to be run before any Pstate changes are requested */
611
612 nodes = get_nodes();
613
614 for (i = 0; i < nodes; i++) {
Timothy Pearson38629f52015-09-05 18:46:54 -0500615 printk(BIOS_DEBUG, "Prep FID/VID Node:%02x\n", i);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000616 dev = NODE_PCI(i, 3);
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200617 uint64_t cpuRev = mctGetLogicalCPUID(0xFF);
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200618 u8 procPkg = mctGetProcessorPackageType();
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000619
Xavi Drudis Ferrand7294592011-02-27 23:42:58 +0000620 setVSRamp(dev);
621 /* BKDG r31116 2010-04-22 2.4.1.7 step b F3xD8[VSSlamTime] */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000622 /* Figure out the value for VsSlamTime and program it */
623 recalculateVsSlamTimeSettingOnCorePre(dev);
624
Timothy Pearson38629f52015-09-05 18:46:54 -0500625 config_clk_power_ctrl_reg0(i,cpuRev,procPkg);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000626
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200627 config_power_ctrl_misc_reg(dev,cpuRev,procPkg);
Xavi Drudis Ferran1f93fea2011-02-28 00:24:21 +0000628 config_nb_syn_ptr_adj(dev,cpuRev);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000629
Timothy Pearson38629f52015-09-05 18:46:54 -0500630 config_acpi_pwr_state_ctrl_regs(dev,cpuRev,procPkg);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000631
632 dword = pci_read_config32(dev, 0x80);
Timothy Pearson38629f52015-09-05 18:46:54 -0500633 printk(BIOS_DEBUG, " F3x80: %08x\n", dword);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000634 dword = pci_read_config32(dev, 0x84);
Timothy Pearson38629f52015-09-05 18:46:54 -0500635 printk(BIOS_DEBUG, " F3x84: %08x\n", dword);
Timothy Pearson83abd812015-06-08 19:35:06 -0500636 dword = pci_read_config32(dev, 0xd4);
Timothy Pearson38629f52015-09-05 18:46:54 -0500637 printk(BIOS_DEBUG, " F3xD4: %08x\n", dword);
Timothy Pearson83abd812015-06-08 19:35:06 -0500638 dword = pci_read_config32(dev, 0xd8);
Timothy Pearson38629f52015-09-05 18:46:54 -0500639 printk(BIOS_DEBUG, " F3xD8: %08x\n", dword);
Timothy Pearson83abd812015-06-08 19:35:06 -0500640 dword = pci_read_config32(dev, 0xdc);
Timothy Pearson38629f52015-09-05 18:46:54 -0500641 printk(BIOS_DEBUG, " F3xDC: %08x\n", dword);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000642 }
643}
644
Timothy Pearson730a0432015-10-16 13:51:51 -0500645static void waitCurrentPstate(u32 target_pstate) {
Timothy Pearson0122afb2015-07-30 14:07:15 -0500646 msr_t initial_msr = rdmsr(TSC_MSR);
647 msr_t pstate_msr = rdmsr(CUR_PSTATE_MSR);
648 msr_t tsc_msr;
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200649 u8 timedout;
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000650
Timothy Pearson0122afb2015-07-30 14:07:15 -0500651 /* paranoia ? I fear when we run fixPsNbVidBeforeWR we can enter a
652 * P1 that is a copy of P0, therefore has the same NB DID but the
653 * TSC will count twice per tick, so we have to wait for twice the
654 * count to achieve the desired timeout. But I'm likely to
655 * misunderstand this...
656 */
657 u32 corrected_timeout = ((pstate_msr.lo==1)
658 && (!(rdmsr(0xC0010065).lo & NB_DID_M_ON)) ) ?
659 WAIT_PSTATE_TIMEOUT*2 : WAIT_PSTATE_TIMEOUT;
660 msr_t timeout;
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000661
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200662 timeout.lo = initial_msr.lo + corrected_timeout;
Timothy Pearson0122afb2015-07-30 14:07:15 -0500663 timeout.hi = initial_msr.hi;
664 if ( (((u32)0xffffffff) - initial_msr.lo) < corrected_timeout ) {
665 timeout.hi++;
666 }
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000667
Timothy Pearson0122afb2015-07-30 14:07:15 -0500668 // assuming TSC ticks at 1.25 ns per tick (800 MHz)
669 do {
670 pstate_msr = rdmsr(CUR_PSTATE_MSR);
671 tsc_msr = rdmsr(TSC_MSR);
672 timedout = (tsc_msr.hi > timeout.hi)
673 || ((tsc_msr.hi == timeout.hi) && (tsc_msr.lo > timeout.lo ));
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200674 } while ( (pstate_msr.lo != target_pstate) && (! timedout) );
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000675
Timothy Pearson0122afb2015-07-30 14:07:15 -0500676 if (pstate_msr.lo != target_pstate) {
677 msr_t limit_msr = rdmsr(0xc0010061);
678 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",
679 cpuid_ebx(0x00000001) >> 24, target_pstate, pstate_msr.lo, limit_msr.hi, limit_msr.lo);
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000680
Timothy Pearson0122afb2015-07-30 14:07:15 -0500681 do { // should we just go on instead ?
682 pstate_msr = rdmsr(CUR_PSTATE_MSR);
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200683 } while ( pstate_msr.lo != target_pstate );
Timothy Pearson0122afb2015-07-30 14:07:15 -0500684 }
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000685}
686
687static void set_pstate(u32 nonBoostedPState) {
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600688 msr_t msr;
689 uint8_t skip_wait;
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000690
691 // Transition P0 for calling core.
692 msr = rdmsr(0xC0010062);
693
694 msr.lo = nonBoostedPState;
695 wrmsr(0xC0010062, msr);
696
Timothy Pearson730a0432015-10-16 13:51:51 -0500697 if (is_fam15h()) {
698 /* Do not wait for the first (even) set of cores to transition on Family 15h systems */
699 if ((cpuid_ebx(0x00000001) & 0x01000000))
700 skip_wait = 0;
701 else
702 skip_wait = 1;
703 } else {
704 skip_wait = 0;
705 }
706
707 if (!skip_wait) {
708 /* Wait for core to transition to P0 */
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200709 waitCurrentPstate(nonBoostedPState);
Timothy Pearson730a0432015-10-16 13:51:51 -0500710 }
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000711}
712
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000713static void UpdateSinglePlaneNbVid(void)
714{
715 u32 nbVid, cpuVid;
716 u8 i;
717 msr_t msr;
718
719 /* copy higher voltage (lower VID) of NBVID & CPUVID to both */
720 for (i = 0; i < 5; i++) {
721 msr = rdmsr(PS_REG_BASE + i);
722 nbVid = (msr.lo & PS_CPU_VID_M_ON) >> PS_CPU_VID_SHFT;
723 cpuVid = (msr.lo & PS_NB_VID_M_ON) >> PS_NB_VID_SHFT;
724
725 if (nbVid != cpuVid) {
726 if (nbVid > cpuVid)
727 nbVid = cpuVid;
728
729 msr.lo = msr.lo & PS_BOTH_VID_OFF;
730 msr.lo = msr.lo | (u32) ((nbVid) << PS_NB_VID_SHFT);
731 msr.lo = msr.lo | (u32) ((nbVid) << PS_CPU_VID_SHFT);
732 wrmsr(PS_REG_BASE + i, msr);
733 }
734 }
735}
736
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000737static void fixPsNbVidBeforeWR(u32 newNbVid, u32 coreid, u32 dev, u8 pviMode)
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600738{
739 msr_t msr;
740 u8 startup_pstate;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000741
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600742 /* This function sets NbVid before the warm reset.
743 * Get StartupPstate from MSRC001_0071.
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000744 * Read Pstate register pointed by [StartupPstate].
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600745 * and copy its content to P0 and P1 registers.
746 * Copy newNbVid to P0[NbVid].
747 * transition to P1 on all cores,
748 * then transition to P0 on core 0.
749 * Wait for MSRC001_0063[CurPstate] = 000b on core 0.
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200750 * see BKDG rev 3.48 2.4.2.9.1 BIOS NB COF and VID Configuration
751 * for SVI and Single-Plane PVI Systems
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600752 */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000753
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600754 msr = rdmsr(0xc0010071);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000755 startup_pstate = (msr.hi >> (32 - 32)) & 0x07;
756
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000757 /* Copy startup pstate to P1 and P0 MSRs. Set the maxvid for
758 * this node in P0. Then transition to P1 for corex and P0
759 * for core0. These setting will be cleared by the warm reset
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000760 */
761 msr = rdmsr(0xC0010064 + startup_pstate);
762 wrmsr(0xC0010065, msr);
763 wrmsr(0xC0010064, msr);
764
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200765 /* missing step 2 from BDKG , F3xDC[PstateMaxVal] =
766 * max(1,F3xDC[PstateMaxVal] ) because it would take
767 * synchronization between cores and we don't think
768 * PstatMaxVal is going to be 0 on cold reset anyway ?
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000769 */
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200770 if (!(pci_read_config32(dev, 0xdc) & (~PS_MAX_VAL_MASK))) {
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600771 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 +0000772 };
773
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000774 msr.lo &= ~0xFE000000; // clear nbvid
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000775 msr.lo |= (newNbVid << 25);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000776 wrmsr(0xC0010064, msr);
777
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000778 if (pviMode) { /* single plane*/
779 UpdateSinglePlaneNbVid();
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200780 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000781
782 // Transition to P1 for all APs and P0 for core0.
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200783 set_pstate(1);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000784
785 if (coreid == 0) {
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200786 set_pstate(0);
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600787 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000788
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000789 /* missing step 7 (restore PstateMax to 0 if needed) because
790 * we skipped step 2
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000791 */
792
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000793}
794
Xavi Drudis Ferranf7ef4212011-02-27 23:58:34 +0000795static u32 needs_NB_COF_VID_update(void)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000796{
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000797 u8 nb_cof_vid_update;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000798 u8 nodes;
799 u8 i;
800
Timothy Pearson730a0432015-10-16 13:51:51 -0500801 if (is_fam15h())
802 return 0;
803
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000804 /* If any node has nb_cof_vid_update set all nodes need an update. */
805 nodes = get_nodes();
806 nb_cof_vid_update = 0;
807 for (i = 0; i < nodes; i++) {
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200808 uint64_t cpuRev = mctGetLogicalCPUID(i);
809 u32 nbCofVidUpdateDefined = (cpuRev & (AMD_FAM10_LT_D));
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000810 if (nbCofVidUpdateDefined
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200811 && (pci_read_config32(NODE_PCI(i, 3), 0x1FC)
812 & NB_COF_VID_UPDATE_MASK)) {
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000813 nb_cof_vid_update = 1;
814 break;
815 }
816 }
Xavi Drudis Ferranf7ef4212011-02-27 23:58:34 +0000817 return nb_cof_vid_update;
818}
819
Xavi Drudis Ferran1f4fffb2011-02-28 00:00:51 +0000820static u32 init_fidvid_core(u32 nodeid, u32 coreid)
Xavi Drudis Ferranf7ef4212011-02-27 23:58:34 +0000821{
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200822 pci_devfn_t dev;
Xavi Drudis Ferranf7ef4212011-02-27 23:58:34 +0000823 u32 vid_max;
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000824 u32 fid_max = 0;
Xavi Drudis Ferranf7ef4212011-02-27 23:58:34 +0000825 u8 nb_cof_vid_update = needs_NB_COF_VID_update();
826 u8 pvimode;
827 u32 reg1fc;
Xavi Drudis Ferranf7ef4212011-02-27 23:58:34 +0000828
829 /* Steps 1-6 of BIOS NB COF and VID Configuration
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000830 * for SVI and Single-Plane PVI Systems. BKDG 2.4.2.9 #31116 rev 3.48
Xavi Drudis Ferranf7ef4212011-02-27 23:58:34 +0000831 */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000832 dev = NODE_PCI(nodeid, 3);
Timothy Pearson730a0432015-10-16 13:51:51 -0500833 if (is_fam15h())
834 pvimode = 0;
835 else
836 pvimode = pci_read_config32(dev, PW_CTL_MISC) & PVI_MODE;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000837 reg1fc = pci_read_config32(dev, 0x1FC);
838
839 if (nb_cof_vid_update) {
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200840 vid_max = (reg1fc & SINGLE_PLANE_NB_VID_MASK ) >> SINGLE_PLANE_NB_VID_SHIFT;
841 fid_max = (reg1fc & SINGLE_PLANE_NB_FID_MASK ) >> SINGLE_PLANE_NB_FID_SHIFT;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000842
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200843 if (!pvimode) { /* SVI, dual power plane */
844 vid_max = vid_max - ((reg1fc & DUAL_PLANE_NB_VID_OFF_MASK ) >> DUAL_PLANE_NB_VID_SHIFT );
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000845 fid_max = fid_max + ((reg1fc & DUAL_PLANE_NB_FID_OFF_MASK ) >> DUAL_PLANE_NB_FID_SHIFT );
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000846 }
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000847 /* write newNbVid to P-state Reg's NbVid always if NbVidUpdatedAll=1 */
Timothy Pearson730a0432015-10-16 13:51:51 -0500848 fixPsNbVidBeforeWR(vid_max, coreid, dev, pvimode);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000849
850 /* fid setup is handled by the BSP at the end. */
851
852 } else { /* ! nb_cof_vid_update */
853 /* Use max values */
854 if (pvimode)
855 UpdateSinglePlaneNbVid();
856 }
857
Xavi Drudis Ferran1f4fffb2011-02-28 00:00:51 +0000858 return ((nb_cof_vid_update << 16) | (fid_max << 8));
859
860}
861
Xavi Drudis Ferran6bdc83b2011-02-28 03:56:52 +0000862static void init_fidvid_ap(u32 apicid, u32 nodeid, u32 coreid)
Xavi Drudis Ferran1f4fffb2011-02-28 00:00:51 +0000863{
864 u32 send;
865
866 printk(BIOS_DEBUG, "FIDVID on AP: %02x\n", apicid);
867
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200868 send = init_fidvid_core(nodeid, coreid);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000869 send |= (apicid << 24); // ap apicid
870
871 // Send signal to BSP about this AP max fid
872 // This also indicates this AP is ready for warm reset (if required).
873 lapic_write(LAPIC_MSG_REG, send | F10_APSTATE_RESET);
874}
875
876static u32 calc_common_fid(u32 fid_packed, u32 fid_packed_new)
877{
878 u32 fidmax;
879 u32 fidmax_new;
880
881 fidmax = (fid_packed >> 8) & 0xFF;
882
883 fidmax_new = (fid_packed_new >> 8) & 0xFF;
884
885 if (fidmax > fidmax_new) {
886 fidmax = fidmax_new;
887 }
888
889 fid_packed &= 0xFF << 16;
890 fid_packed |= (fidmax << 8);
891 fid_packed |= fid_packed_new & (0xFF << 16); // set nb_cof_vid_update
892
893 return fid_packed;
894}
895
896static void init_fidvid_bsp_stage1(u32 ap_apicid, void *gp)
897{
898 u32 readback = 0;
899 u32 timeout = 1;
900
901 struct fidvid_st *fvp = gp;
902 int loop;
903
904 print_debug_fv("Wait for AP stage 1: ap_apicid = ", ap_apicid);
905
906 loop = 100000;
907 while (--loop > 0) {
908 if (lapic_remote_read(ap_apicid, LAPIC_MSG_REG, &readback) != 0)
909 continue;
Timothy Pearson730a0432015-10-16 13:51:51 -0500910 if (((readback & 0x3f) == F10_APSTATE_RESET)
911 || (is_fam15h() && ((readback & 0x3f) == F10_APSTATE_ASLEEP))) {
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000912 timeout = 0;
913 break; /* target ap is in stage 1 */
914 }
915 }
916
917 if (timeout) {
918 printk(BIOS_DEBUG, "%s: timed out reading from ap %02x\n",
919 __func__, ap_apicid);
920 return;
921 }
922
923 print_debug_fv("\treadback = ", readback);
924
925 fvp->common_fid = calc_common_fid(fvp->common_fid, readback);
926
927 print_debug_fv("\tcommon_fid(packed) = ", fvp->common_fid);
928
929}
930
Xavi Drudis Ferranc3132102011-02-28 03:49:28 +0000931static void fixPsNbVidAfterWR(u32 newNbVid, u8 NbVidUpdatedAll,u8 pviMode)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000932{
933 msr_t msr;
934 u8 i;
935 u8 StartupPstate;
936
Xavi Drudis Ferran26f97d22011-02-28 03:08:06 +0000937 /* BKDG 2.4.2.9.1 11-12
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200938 * This function copies newNbVid to NbVid bits in P-state
Xavi Drudis Ferran26f97d22011-02-28 03:08:06 +0000939 * Registers[4:0] if its NbDid bit=0, and IddValue!=0 in case of
940 * NbVidUpdatedAll =0 or copies newNbVid to NbVid bits in
941 * P-state Registers[4:0] if its IddValue!=0 in case of
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000942 * NbVidUpdatedAll=1. Then transition to StartPstate.
943 */
944
945 /* write newNbVid to P-state Reg's NbVid if its NbDid=0 */
946 for (i = 0; i < 5; i++) {
947 msr = rdmsr(0xC0010064 + i);
948 /* NbDid (bit 22 of P-state Reg) == 0 or NbVidUpdatedAll = 1 */
Xavi Drudis Ferranc3132102011-02-28 03:49:28 +0000949 if ( (msr.hi & PS_IDD_VALUE_MASK)
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200950 && (msr.hi & PS_EN_MASK)
951 &&(((msr.lo & PS_NB_DID_MASK) == 0) || NbVidUpdatedAll)) {
Xavi Drudis Ferran26f97d22011-02-28 03:08:06 +0000952 msr.lo &= PS_NB_VID_M_OFF;
953 msr.lo |= (newNbVid & 0x7F) << PS_NB_VID_SHFT;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000954 wrmsr(0xC0010064 + i, msr);
955 }
956 }
957
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200958 /* Not documented. Would overwrite Nb_Vids just copied
959 * should we just update cpu_vid or nothing at all ?
Xavi Drudis Ferran26f97d22011-02-28 03:08:06 +0000960 */
961 if (pviMode) { //single plane
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200962 UpdateSinglePlaneNbVid();
Xavi Drudis Ferran26f97d22011-02-28 03:08:06 +0000963 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000964 /* For each core in the system, transition all cores to StartupPstate */
965 msr = rdmsr(0xC0010071);
966 StartupPstate = msr.hi & 0x07;
Xavi Drudis Ferranc3132102011-02-28 03:49:28 +0000967
Xavi Drudis Ferran26f97d22011-02-28 03:08:06 +0000968 /* Set and wait for StartupPstate to set. */
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200969 set_pstate(StartupPstate);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000970
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000971}
972
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000973static void finalPstateChange(void)
974{
Martin Roth4c3ab732013-07-08 16:23:54 -0600975 /* Enable P0 on all cores for best performance.
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000976 * Linux can slow them down later if need be.
977 * It is safe since they will be in C1 halt
978 * most of the time anyway.
979 */
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000980 set_pstate(0);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000981}
982
Damien Zammit75a3d1f2016-11-28 00:29:10 +1100983void init_fidvid_stage2(u32 apicid, u32 nodeid)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000984{
985 msr_t msr;
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200986 pci_devfn_t dev;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000987 u32 reg1fc;
988 u32 dtemp;
989 u32 nbvid;
Xavi Drudis Ferranf7ef4212011-02-27 23:58:34 +0000990 u8 nb_cof_vid_update = needs_NB_COF_VID_update();
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000991 u8 NbVidUpdateAll;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000992 u8 pvimode;
993
994 /* After warm reset finish the fid/vid setup for all cores. */
995
996 /* If any node has nb_cof_vid_update set all nodes need an update. */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000997
998 dev = NODE_PCI(nodeid, 3);
Timothy Pearson730a0432015-10-16 13:51:51 -0500999 if (is_fam15h())
1000 pvimode = 0;
1001 else
1002 pvimode = (pci_read_config32(dev, 0xA0) >> 8) & 1;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001003 reg1fc = pci_read_config32(dev, 0x1FC);
1004 nbvid = (reg1fc >> 7) & 0x7F;
1005 NbVidUpdateAll = (reg1fc >> 1) & 1;
1006
1007 if (nb_cof_vid_update) {
Xavi Drudis Ferran26f97d22011-02-28 03:08:06 +00001008 if (!pvimode) { /* SVI */
1009 nbvid = nbvid - ((reg1fc >> 17) & 0x1F);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001010 }
Xavi Drudis Ferran26f97d22011-02-28 03:08:06 +00001011 /* write newNbVid to P-state Reg's NbVid if its NbDid=0 */
1012 fixPsNbVidAfterWR(nbvid, NbVidUpdateAll,pvimode);
Martin Rothe5f2d4c2017-07-23 16:07:31 -06001013 } else { /* !nb_cof_vid_update */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001014 if (pvimode)
1015 UpdateSinglePlaneNbVid();
1016 }
1017 dtemp = pci_read_config32(dev, 0xA0);
1018 dtemp &= PLLLOCK_OFF;
1019 dtemp |= PLLLOCK_DFT_L;
1020 pci_write_config32(dev, 0xA0, dtemp);
1021
Elyes HAOUAS2765a892016-09-01 19:44:56 +02001022 dualPlaneOnly(dev);
1023 applyBoostFIDOffset(dev, nodeid);
1024 enableNbPState1(dev);
Xavi Drudis Ferran5bcedee2011-02-28 03:25:07 +00001025
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001026 finalPstateChange();
1027
Timothy Pearson730a0432015-10-16 13:51:51 -05001028 if (!is_fam15h()) {
1029 /* Set TSC to tick at the P0 ndfid rate */
1030 msr = rdmsr(HWCR);
1031 msr.lo |= 1 << 24;
1032 wrmsr(HWCR, msr);
1033 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001034}
1035
1036
Martin Roth5f46af62017-06-24 13:24:26 -06001037#if IS_ENABLED(CONFIG_SET_FIDVID_STORE_AP_APICID_AT_FIRST)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001038struct ap_apicid_st {
1039 u32 num;
1040 // it could use 256 bytes for 64 node quad core system
1041 u8 apicid[NODE_NUMS * 4];
1042};
1043
1044static void store_ap_apicid(unsigned ap_apicid, void *gp)
1045{
1046 struct ap_apicid_st *p = gp;
1047
1048 p->apicid[p->num++] = ap_apicid;
1049
1050}
1051#endif
1052
1053
Damien Zammit75a3d1f2016-11-28 00:29:10 +11001054int init_fidvid_bsp(u32 bsp_apicid, u32 nodes)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001055{
Martin Roth5f46af62017-06-24 13:24:26 -06001056#if IS_ENABLED(CONFIG_SET_FIDVID_STORE_AP_APICID_AT_FIRST)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001057 struct ap_apicid_st ap_apicidx;
1058 u32 i;
1059#endif
1060 struct fidvid_st fv;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001061
1062 printk(BIOS_DEBUG, "FIDVID on BSP, APIC_id: %02x\n", bsp_apicid);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001063
1064 /* Steps 1-6 of BIOS NB COF and VID Configuration
1065 * for SVI and Single-Plane PVI Systems.
1066 */
Timothy Pearson730a0432015-10-16 13:51:51 -05001067 fv.common_fid = init_fidvid_core(0, 0);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001068
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001069 print_debug_fv("BSP fid = ", fv.common_fid);
1070
Martin Roth5f46af62017-06-24 13:24:26 -06001071#if IS_ENABLED(CONFIG_SET_FIDVID_STORE_AP_APICID_AT_FIRST) && \
1072 !IS_ENABLED(CONFIG_SET_FIDVID_CORE0_ONLY)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001073 /* For all APs (We know the APIC ID of all APs even when the APIC ID
1074 is lifted) remote read from AP LAPIC_MSG_REG about max fid.
1075 Then calculate the common max fid that can be used for all
1076 APs and BSP */
1077 ap_apicidx.num = 0;
1078
Timothy Pearson0122afb2015-07-30 14:07:15 -05001079 for_each_ap(bsp_apicid, CONFIG_SET_FIDVID_CORE_RANGE, -1, store_ap_apicid, &ap_apicidx);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001080
1081 for (i = 0; i < ap_apicidx.num; i++) {
1082 init_fidvid_bsp_stage1(ap_apicidx.apicid[i], &fv);
1083 }
1084#else
Timothy Pearson0122afb2015-07-30 14:07:15 -05001085 for_each_ap(bsp_apicid, CONFIG_SET_FIDVID_CORE0_ONLY, -1, init_fidvid_bsp_stage1, &fv);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001086#endif
1087
1088 print_debug_fv("common_fid = ", fv.common_fid);
1089
1090 if (fv.common_fid & (1 << 16)) { /* check nb_cof_vid_update */
1091
1092 // Enable the common fid and other settings.
1093 enable_fid_change((fv.common_fid >> 8) & 0x1F);
1094
1095 // nbfid change need warm reset, so reset at first
1096 return 1;
1097 }
1098
1099 return 0; // No FID/VID changes. Don't reset
1100}