blob: 1c2b214dce51f8269ca3f7c52b88be5c5e8dd3ec [file] [log] [blame]
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001/*
2 * This file is part of the coreboot project.
3 *
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00004 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000012 */
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000013/*
Stefan Reinauer5ff7c132011-10-31 12:56:45 -070014 * This file initializes the CPU cores for voltage and frequency settings
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000015 * in the different power states.
16 */
17/*
18
19checklist (functions are in this file if no source file named)
Stefan Reinauer5ff7c132011-10-31 12:56:45 -070020Fam10 Bios and Kernel Development Guide #31116, rev 3.48, April 22, 2010
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000021
222.4.2.6 Requirements for p-states
23
241.- F3x[84:80] According to table 100 : prep_fid_change
25
Stefan Reinauer5ff7c132011-10-31 12:56:45 -0700262.- COF/VID :
27 2.4.2.9.1 Steps 1,3-6 and warning for 2,7 if they apply
Elyes HAOUAS2765a892016-09-01 19:44:56 +020028 fixPsNbVidBeforeWR(...)
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000029 2.4.2.9.1 Step 8 enable_fid_change
Elyes HAOUAS2765a892016-09-01 19:44:56 +020030 We do this for all nodes, I don't understand BKDG 100% on
31 whether this is or isn't meant by "on the local
32 processor". Must be OK.
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000033 2.4.2.9.1 Steps 9-10 (repeat 1-7 and reset) romstage.c/init_cpus ?
34 2.4.2.9.1 Steps 11-12 init_fidvid_stage2
Stefan Reinauer5ff7c132011-10-31 12:56:45 -070035 2.4.2.9.2 DualPlane PVI : Not supported, don't know how to detect,
Elyes HAOUAS2765a892016-09-01 19:44:56 +020036 needs specific circuitry.
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000037
383.- 2.4.2.7 dualPlaneOnly(dev)
39
Timothy Pearson730a0432015-10-16 13:51:51 -0500404.- 2.4.2.8 applyBoostFIDOffset(dev, nodeid)
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000041
Stefan Reinauer5ff7c132011-10-31 12:56:45 -0700425.- enableNbPState1(dev)
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000043
Stefan Reinauer5ff7c132011-10-31 12:56:45 -0700446.- 2.4.1.7
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000045 a) UpdateSinglePlaneNbVid()
46 b) setVSRamp(), called from prep_fid_change
47 c) prep_fid_change
Stefan Reinauer5ff7c132011-10-31 12:56:45 -070048 d) improperly, for lack of voltage regulator details?,
Elyes HAOUAS2765a892016-09-01 19:44:56 +020049 F3xA0[PsiVidEn] in defaults.h
50 F3xA0[PsiVid] in init_cpus.c AMD_SetupPSIVID_d (before prep_fid_change)
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000051
Stefan Reinauer5ff7c132011-10-31 12:56:45 -0700527.- TODO (Core Performance Boost is only available in revision E cpus, and we
Elyes HAOUAS2765a892016-09-01 19:44:56 +020053 don't seem to support those yet, at least they don't have any
54 constant in amddefs.h )
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000055
Stefan Reinauer5ff7c132011-10-31 12:56:45 -0700568.- FIXME ? Transition to min Pstate according to 2.4.2.15.3 is required
57 by 2.4.2.6 after warm reset. But 2.4.2.15 states that it is not required
58 if the warm reset is issued by coreboot to update NbFid. So it is required
59 or not ? How can I tell who issued warm reset ?
Martin Rothe18e6422017-06-03 20:03:18 -060060 coreboot transitions to P0 instead, which is not recommended, and does
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000061 not follow 2.4.2.15.2 to do so.
62
Stefan Reinauer5ff7c132011-10-31 12:56:45 -0700639.- TODO Requires information on current delivery capability
64 (depends on mainboard and maybe power supply ?). One might use a config
Martin Roth4c3ab732013-07-08 16:23:54 -060065 option with the maximum number of Amperes that the board can deliver to CPU.
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000066
6710.- [Multiprocessor] TODO 2.4.2.12
Stefan Reinauer5ff7c132011-10-31 12:56:45 -070068 [Uniprocessor] FIXME ? We call setPStateMaxVal() in init_fidvid_stage2,
69 but not sure this is what is meant by "Determine the valid set of
70 P-states based on enabled P-states indicated
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000071 in MSRC001_00[68:64][PstateEn]" in 2.4.2.6-10
72
7311.- finalPstateChange() from init_fidvid_Stage2 (BKDG says just "may", anyway)
74
Timothy Pearsona89accd2015-02-20 11:54:09 -06007512.- generate ACPI for p-states.
Patrick Georgia425b962015-03-05 20:18:21 +010076 generated in powernow_acpi.c amd_generate_powernow()
Stefan Reinauer5ff7c132011-10-31 12:56:45 -070077
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000078"must also be completed"
79
80a.- PllLockTime set in ruleset in defaults.h
Stefan Reinauer5ff7c132011-10-31 12:56:45 -070081 BKDG says set it "If MSRC001_00[68:64][CpuFid] is different between
82 any two enabled P-states", but since it does not say "only if"
Xavi Drudis Ferranb6711722011-02-28 03:59:34 +000083 I guess it is safe to do it always.
84
85b.- prep_fid_change(...)
86
87 */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000088
Elyes HAOUAS20eaef02019-03-29 17:45:28 +010089#include <console/console.h>
Elyes HAOUAS400ce552018-10-12 10:54:30 +020090#include <cpu/amd/msr.h>
Elyes HAOUAS276d46a2019-06-16 11:08:25 +020091#include <device/pci_ops.h>
Jacob Garber5cf9ccc2019-08-08 13:35:31 -060092#include <stdint.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{
Julius Wernercd49cce2019-03-05 16:53:33 -080097#if 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{
Julius Wernercd49cce2019-03-05 16:53:33 -0800104#if 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{
Julius Wernercd49cce2019-03-05 16:53:33 -0800111#if 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;
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200149 msr_t msr = rdmsr(PSTATE_0_MSR);
Timothy Pearson730a0432015-10-16 13:51:51 -0500150 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;
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200154 wrmsr(PSTATE_0_MSR, msr);
Timothy Pearson730a0432015-10-16 13:51:51 -0500155 } 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++) {
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200176 msr_t msr = rdmsr(PSTATE_0_MSR + i);
Timothy Pearson83abd812015-06-08 19:35:06 -0500177 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);
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200181 wrmsr(PSTATE_0_MSR + i, msr);
Timothy Pearson83abd812015-06-08 19:35:06 -0500182 }
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++) {
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200192 msr_t msr = rdmsr(PSTATE_0_MSR + i);
Timothy Pearson83abd812015-06-08 19:35:06 -0500193 if (msr.hi & PS_IDD_VALUE_MASK) {
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200194 msr.hi |= PS_EN_MASK;
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200195 wrmsr(PSTATE_0_MSR + i, msr);
Timothy Pearson83abd812015-06-08 19:35:06 -0500196 }
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)) {
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200218 if (cpuid_edx(CPUID_EXT_PM) & CPB_MASK) {
Timothy Pearson83abd812015-06-08 19:35:06 -0500219 // revision E only, but E is apparently not supported yet, therefore untested
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200220 msr_t minPstate = rdmsr(PSTATE_1_MSR);
221 wrmsr(PSTATE_1_MSR, rdmsr(PSTATE_4_MSR));
222 wrmsr(PSTATE_4_MSR, minPstate);
Timothy Pearson83abd812015-06-08 19:35:06 -0500223 } else {
224 msr_t msr;
225 msr.lo=0; msr.hi=0;
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200226 wrmsr(PSTATE_0_MSR, rdmsr(PSTATE_4_MSR));
227 wrmsr(PSTATE_4_MSR, msr);
Timothy Pearson83abd812015-06-08 19:35:06 -0500228 }
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. */
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200310 msr = rdmsr(PSTATE_0_MSR);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000311 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 */
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200328 msr = rdmsr(PS_LIM_REG);
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 */
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200332 msr = rdmsr(PSTATE_0_MSR + bValue);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000333 lowVoltageVid = (u8) ((msr.lo >> PS_CPU_VID_SHFT) & 0x7F);
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200334 if (!(msr.hi & 0x80000000)) {
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200335 printk(BIOS_ERR, "P-state info in MSR%8x is invalid !!!\n",
336 PSTATE_0_MSR + bValue);
337 lowVoltageVid = (u8) ((pci_read_config32(dev, 0x1E0+(bValue*4))
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200338 >> PS_CPU_VID_SHFT) & 0x7F);
Xavi Drudis Ferran82b241a2011-02-28 03:32:23 +0000339 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000340
341 /* If SVI, we only care about CPU VID.
342 * If PVI, determine the higher voltage b/t NB and CPU
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200343 * BKDG 2.4.1.7 (a)
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600344 */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000345 if (pviModeFlag) {
346 bValue = (u8) ((msr.lo >> PS_NB_VID_SHFT) & 0x7F);
347 if (lowVoltageVid > bValue)
348 lowVoltageVid = bValue;
349 }
350
351 /* Get AltVID */
Timothy Pearson83abd812015-06-08 19:35:06 -0500352 dtemp = pci_read_config32(dev, 0xdc);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000353 bValue = (u8) (dtemp & BIT_MASK_7);
354
355 /* Use the VID with the lowest voltage (higher VID) */
356 if (lowVoltageVid < bValue)
357 lowVoltageVid = bValue;
358
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200359 u8 mobileFlag = get_platform_type() & AMD_PTYPE_MOB;
Xavi Drudis Ferran82b241a2011-02-28 03:32:23 +0000360 minimumSlamTime = (mobileFlag?2:4) * (vidTo100uV(highVoltageVid) - vidTo100uV(lowVoltageVid)); /* * 0.01 us */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000361
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000362
363 /* Now round up to nearest register setting.
364 * Note that if we don't find a value, we
365 * will fall through to a value of 7
366 */
367 for (bValue = 0; bValue < 7; bValue++) {
368 if (minimumSlamTime <= vSlamTimes[bValue])
369 break;
370 }
371
372 /* Apply the value */
373 dtemp = pci_read_config32(dev, 0xD8);
374 dtemp &= VSSLAM_MASK;
375 dtemp |= bValue;
376 pci_write_config32(dev, 0xd8, dtemp);
377}
378
Timothy Pearson5173bb72015-08-02 21:31:48 -0500379static u32 nb_clk_did(uint8_t node, uint64_t cpuRev, uint8_t procPkg) {
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200380 uint8_t link0isGen3 = 0;
381 uint8_t offset;
382 if (AMD_CpuFindCapability(node, 0, &offset)) {
Timothy Pearsonf8549e82015-09-07 22:26:55 -0500383 link0isGen3 = (AMD_checkLinkType(node, offset) & HTPHY_LINKTYPE_HT3 );
Xavi Drudis Ferranadb23a52011-02-28 00:10:37 +0000384 }
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200385 /* FIXME: NB_CLKDID should be 101b for AMD_DA_C2 in package
386 S1g3 in link Gen3 mode, but I don't know how to tell
387 package S1g3 from S1g4 */
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000388 if ((cpuRev & AMD_DA_C2) && (procPkg & AMD_PKGTYPE_S1gX)
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200389 && link0isGen3) {
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200390 return 5; /* divide clk by 128*/
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200391 } else {
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200392 return 4; /* divide clk by 16 */
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200393 }
Xavi Drudis Ferranadb23a52011-02-28 00:10:37 +0000394}
395
396
397static u32 power_up_down(int node, u8 procPkg) {
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600398 uint32_t dword=0;
399 /* from CPU rev guide #41322 rev 3.74 June 2010 Table 26 */
400 u8 singleLinkFlag = ((procPkg == AMD_PKGTYPE_AM3_2r2)
401 || (procPkg == AMD_PKGTYPE_S1gX)
402 || (procPkg == AMD_PKGTYPE_ASB2));
Xavi Drudis Ferranadb23a52011-02-28 00:10:37 +0000403
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600404 if (singleLinkFlag) {
405 /*
406 * PowerStepUp=01000b - 50nS
407 * PowerStepDown=01000b - 50ns
Xavi Drudis Ferrana5cbd252011-02-27 23:45:34 +0000408 */
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600409 dword |= PW_STP_UP50 | PW_STP_DN50;
410 } else {
411 uint32_t dispRefModeEn = (pci_read_config32(NODE_PCI(node,0),0x68) >> 24) & 1;
412 uint32_t isocEn = 0;
413 int j;
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200414 for (j=0; (j<4) && (!isocEn); j++ ) {
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600415 u8 offset;
416 if (AMD_CpuFindCapability(node, j, &offset)) {
417 isocEn = (pci_read_config32(NODE_PCI(node,0),offset+4) >>12) & 1;
418 }
Xavi Drudis Ferrana5cbd252011-02-27 23:45:34 +0000419 }
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600420
421 if (is_fam15h()) {
422 /* Family 15h always uses 100ns for multilink processors */
423 dword |= PW_STP_UP100 | PW_STP_DN100;
424 } else if (dispRefModeEn || isocEn) {
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200425 dword |= PW_STP_UP50 | PW_STP_DN50;
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600426 } else {
427 /* get number of cores for PowerStepUp & PowerStepDown in server
428 * 1 core - 400nS - 0000b
429 * 2 cores - 200nS - 0010b
430 * 3 cores - 133nS -> 100nS - 0011b
431 * 4 cores - 100nS - 0011b
432 */
433 switch (get_core_num_in_bsp(node)) {
434 case 0:
435 dword |= PW_STP_UP400 | PW_STP_DN400;
436 break;
437 case 1:
438 case 2:
439 dword |= PW_STP_UP200 | PW_STP_DN200;
440 break;
441 case 3:
442 dword |= PW_STP_UP100 | PW_STP_DN100;
443 break;
444 default:
445 dword |= PW_STP_UP100 | PW_STP_DN100;
446 break;
447 }
448 }
Xavi Drudis Ferrana5cbd252011-02-27 23:45:34 +0000449 }
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600450
451 return dword;
Xavi Drudis Ferrand26e5e62011-02-27 23:56:00 +0000452}
453
Timothy Pearson5173bb72015-08-02 21:31:48 -0500454static void config_clk_power_ctrl_reg0(uint8_t node, uint64_t cpuRev, uint8_t procPkg) {
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200455
456 pci_devfn_t dev = NODE_PCI(node, 3);
Xavi Drudis Ferrand26e5e62011-02-27 23:56:00 +0000457
Xavi Drudis Ferrand26e5e62011-02-27 23:56:00 +0000458 /* Program fields in Clock Power/Control register0 (F3xD4) */
459
460 /* set F3xD4 Clock Power/Timing Control 0 Register
461 * NbClkDidApplyAll=1b
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000462 * NbClkDid=100b or 101b
Xavi Drudis Ferrand26e5e62011-02-27 23:56:00 +0000463 * PowerStepUp= "platform dependent"
464 * PowerStepDown= "platform dependent"
465 * LinkPllLink=01b
Xavi Drudis Ferranadb23a52011-02-28 00:10:37 +0000466 * ClkRampHystCtl=HW default
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200467 * ClkRampHystSel=1111b
Xavi Drudis Ferrand26e5e62011-02-27 23:56:00 +0000468 */
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200469 uint32_t dword= pci_read_config32(dev, 0xd4);
Xavi Drudis Ferrand26e5e62011-02-27 23:56:00 +0000470 dword &= CPTC0_MASK;
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200471 dword |= NB_CLKDID_ALL | LNK_PLL_LOCK | CLK_RAMP_HYST_SEL_VAL;
472 dword |= (nb_clk_did(node,cpuRev,procPkg) << NB_CLKDID_SHIFT);
Xavi Drudis Ferranadb23a52011-02-28 00:10:37 +0000473
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200474 dword |= power_up_down(node, procPkg);
Xavi Drudis Ferrand26e5e62011-02-27 23:56:00 +0000475
476 pci_write_config32(dev, 0xd4, dword);
477
Xavi Drudis Ferrana5cbd252011-02-27 23:45:34 +0000478}
479
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200480static void config_power_ctrl_misc_reg(pci_devfn_t dev, uint64_t cpuRev,
481 uint8_t procPkg)
482{
Xavi Drudis Ferran9683b1d2011-02-27 23:47:57 +0000483 /* check PVI/SVI */
Timothy Pearson5173bb72015-08-02 21:31:48 -0500484 uint32_t dword = pci_read_config32(dev, 0xa0);
Xavi Drudis Ferran0e5d3e12011-02-28 00:18:43 +0000485
Timothy Pearson38629f52015-09-05 18:46:54 -0500486 /* BKDG r31116 2010-04-22 2.4.1.7 step b F3xA0[VSSlamVidMod] */
487 /* PllLockTime and PsiVidEn set in ruleset in defaults.h */
Xavi Drudis Ferran9683b1d2011-02-27 23:47:57 +0000488 if (dword & PVI_MODE) { /* PVI */
489 /* set slamVidMode to 0 for PVI */
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200490 dword &= VID_SLAM_OFF;
Xavi Drudis Ferran9683b1d2011-02-27 23:47:57 +0000491 } else { /* SVI */
492 /* set slamVidMode to 1 for SVI */
Xavi Drudis Ferran0e5d3e12011-02-28 00:18:43 +0000493 dword |= VID_SLAM_ON;
Timothy Pearson38629f52015-09-05 18:46:54 -0500494 }
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200495 /* set the rest of A0 since we're at it... */
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000496
Timothy Pearson38629f52015-09-05 18:46:54 -0500497 if (cpuRev & (AMD_DA_Cx | AMD_RB_C3 )) {
498 dword |= NB_PSTATE_FORCE_ON;
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000499 } // else should we clear it ?
Xavi Drudis Ferran0e5d3e12011-02-28 00:18:43 +0000500
501
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200502 if ((procPkg == AMD_PKGTYPE_G34) || (procPkg == AMD_PKGTYPE_C32) ) {
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200503 dword |= BP_INS_TRI_EN_ON;
Xavi Drudis Ferran9683b1d2011-02-27 23:47:57 +0000504 }
Xavi Drudis Ferran0e5d3e12011-02-28 00:18:43 +0000505
506 /* TODO: look into C1E state and F3xA0[IdleExitEn]*/
Julius Wernercd49cce2019-03-05 16:53:33 -0800507 #if CONFIG(SVI_HIGH_FREQ)
Timothy Pearson38629f52015-09-05 18:46:54 -0500508 if (cpuRev & AMD_FAM10_C3) {
509 dword |= SVI_HIGH_FREQ_ON;
510 }
511 #endif
512 pci_write_config32(dev, 0xa0, dword);
Xavi Drudis Ferran9683b1d2011-02-27 23:47:57 +0000513}
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000514
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200515static void config_nb_syn_ptr_adj(pci_devfn_t dev, uint64_t cpuRev)
516{
Xavi Drudis Ferran1d80e512011-02-27 23:50:30 +0000517 /* Note the following settings are additional from the ported
518 * function setFidVidRegs()
519 */
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200520 /* adjust FIFO between nb and core clocks to max allowed
521 values (min latency) */
Timothy Pearson5173bb72015-08-02 21:31:48 -0500522 uint32_t nbPstate = pci_read_config32(dev,0x1f0) & NB_PSTATE_MASK;
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200523 uint8_t nbSynPtrAdj;
Timothy Pearson83abd812015-06-08 19:35:06 -0500524 if ((cpuRev & (AMD_DR_Bx | AMD_DA_Cx | AMD_FAM15_ALL) )
525 || ((cpuRev & AMD_RB_C3) && (nbPstate != 0))) {
526 nbSynPtrAdj = 5;
Xavi Drudis Ferran1f93fea2011-02-28 00:24:21 +0000527 } else {
Timothy Pearson83abd812015-06-08 19:35:06 -0500528 nbSynPtrAdj = 6;
Xavi Drudis Ferran1f93fea2011-02-28 00:24:21 +0000529 }
Xavi Drudis Ferran1d80e512011-02-27 23:50:30 +0000530
Timothy Pearson5173bb72015-08-02 21:31:48 -0500531 uint32_t dword = pci_read_config32(dev, 0xdc);
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200532 dword &= ~NB_SYN_PTR_ADJ_MASK;
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000533 dword |= nbSynPtrAdj << NB_SYN_PTR_ADJ_POS;
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200534 /* NbsynPtrAdj set to 5 or 6 per BKDG (needs reset) */
Xavi Drudis Ferran1f93fea2011-02-28 00:24:21 +0000535 pci_write_config32(dev, 0xdc, dword);
Xavi Drudis Ferran1d80e512011-02-27 23:50:30 +0000536}
537
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200538static void config_acpi_pwr_state_ctrl_regs(pci_devfn_t dev, uint64_t cpuRev,
539 uint8_t procPkg)
540{
Timothy Pearson730a0432015-10-16 13:51:51 -0500541 if (is_fam15h()) {
542 /* Family 15h BKDG Rev. 3.14 D18F3x80 recommended settings */
543 pci_write_config32(dev, 0x80, 0xe20be281);
Xavi Drudis Ferran6fcc9612011-02-28 00:31:24 +0000544
Timothy Pearson730a0432015-10-16 13:51:51 -0500545 /* Family 15h BKDG Rev. 3.14 D18F3x84 recommended settings */
546 pci_write_config32(dev, 0x84, 0x01e200e2);
547 } else {
548 /* 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 -0500549 uint32_t dword;
550 uint32_t c1= 1;
Timothy Pearson730a0432015-10-16 13:51:51 -0500551 if (cpuRev & (AMD_DR_Bx)) {
552 // will coreboot ever enable cache scrubbing ?
553 // if it does, will it be enough to check the current state
554 // or should we configure for what we'll set up later ?
555 dword = pci_read_config32(dev, 0x58);
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600556 uint32_t scrubbingCache = dword &
Timothy Pearson730a0432015-10-16 13:51:51 -0500557 ( (0x1F << 16) // DCacheScrub
558 | (0x1F << 8) ); // L2Scrub
559 if (scrubbingCache) {
560 c1 = 0x80;
561 } else {
562 c1 = 0xA0;
563 }
564 } else { // rev C or later
565 // same doubt as cache scrubbing: ok to check current state ?
Timothy Pearson83abd812015-06-08 19:35:06 -0500566 dword = pci_read_config32(dev, 0xdc);
Timothy Pearson606b6ec2015-11-24 14:12:07 -0600567 uint32_t cacheFlushOnHalt = dword & (7 << 16);
Timothy Pearson730a0432015-10-16 13:51:51 -0500568 if (!cacheFlushOnHalt) {
569 c1 = 0x80;
570 }
571 }
572 dword = (c1 << 24) | (0xE641E6);
573 pci_write_config32(dev, 0x84, dword);
Xavi Drudis Ferran6fcc9612011-02-28 00:31:24 +0000574
Timothy Pearson730a0432015-10-16 13:51:51 -0500575 /* FIXME: BKDG Table 100 says if the link is at a Gen1
576 * frequency and the chipset does not support a 10us minimum LDTSTOP
577 * assertion time, then { If ASB2 && SVI then smaf001 = F6h else
578 * smaf001=87h. } else ... I hardly know what it means or how to check
579 * it from here, so I bluntly assume it is false and code here the else,
580 * which is easier
581 */
Xavi Drudis Ferran6fcc9612011-02-28 00:31:24 +0000582
Timothy Pearson5173bb72015-08-02 21:31:48 -0500583 uint32_t smaf001 = 0xE6;
Timothy Pearson730a0432015-10-16 13:51:51 -0500584 if (cpuRev & AMD_DR_Bx ) {
585 smaf001 = 0xA6;
586 } else {
Julius Wernercd49cce2019-03-05 16:53:33 -0800587 #if CONFIG(SVI_HIGH_FREQ)
Timothy Pearson730a0432015-10-16 13:51:51 -0500588 if (cpuRev & (AMD_RB_C3 | AMD_DA_C3)) {
589 smaf001 = 0xF6;
590 }
591 #endif
592 }
Timothy Pearson5173bb72015-08-02 21:31:48 -0500593 uint32_t fidvidChange = 0;
Timothy Pearson730a0432015-10-16 13:51:51 -0500594 if (((cpuRev & AMD_DA_Cx) && (procPkg & AMD_PKGTYPE_S1gX))
595 || (cpuRev & AMD_RB_C3) ) {
596 fidvidChange=0x0B;
597 }
598 dword = (0xE6 << 24) | (fidvidChange << 16)
599 | (smaf001 << 8) | 0x81;
600 pci_write_config32(dev, 0x80, dword);
601 }
Xavi Drudis Ferran40f9b4b02011-02-27 23:53:11 +0000602}
603
Damien Zammit75a3d1f2016-11-28 00:29:10 +1100604void prep_fid_change(void)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000605{
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200606 u32 dword;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000607 u32 nodes;
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200608 pci_devfn_t dev;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000609 int i;
610
611 /* This needs to be run before any Pstate changes are requested */
612
613 nodes = get_nodes();
614
615 for (i = 0; i < nodes; i++) {
Timothy Pearson38629f52015-09-05 18:46:54 -0500616 printk(BIOS_DEBUG, "Prep FID/VID Node:%02x\n", i);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000617 dev = NODE_PCI(i, 3);
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200618 uint64_t cpuRev = mctGetLogicalCPUID(0xFF);
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200619 u8 procPkg = mctGetProcessorPackageType();
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000620
Xavi Drudis Ferrand7294592011-02-27 23:42:58 +0000621 setVSRamp(dev);
622 /* BKDG r31116 2010-04-22 2.4.1.7 step b F3xD8[VSSlamTime] */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000623 /* Figure out the value for VsSlamTime and program it */
624 recalculateVsSlamTimeSettingOnCorePre(dev);
625
Timothy Pearson38629f52015-09-05 18:46:54 -0500626 config_clk_power_ctrl_reg0(i,cpuRev,procPkg);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000627
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200628 config_power_ctrl_misc_reg(dev,cpuRev,procPkg);
Xavi Drudis Ferran1f93fea2011-02-28 00:24:21 +0000629 config_nb_syn_ptr_adj(dev,cpuRev);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000630
Timothy Pearson38629f52015-09-05 18:46:54 -0500631 config_acpi_pwr_state_ctrl_regs(dev,cpuRev,procPkg);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000632
633 dword = pci_read_config32(dev, 0x80);
Timothy Pearson38629f52015-09-05 18:46:54 -0500634 printk(BIOS_DEBUG, " F3x80: %08x\n", dword);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000635 dword = pci_read_config32(dev, 0x84);
Timothy Pearson38629f52015-09-05 18:46:54 -0500636 printk(BIOS_DEBUG, " F3x84: %08x\n", dword);
Timothy Pearson83abd812015-06-08 19:35:06 -0500637 dword = pci_read_config32(dev, 0xd4);
Timothy Pearson38629f52015-09-05 18:46:54 -0500638 printk(BIOS_DEBUG, " F3xD4: %08x\n", dword);
Timothy Pearson83abd812015-06-08 19:35:06 -0500639 dword = pci_read_config32(dev, 0xd8);
Timothy Pearson38629f52015-09-05 18:46:54 -0500640 printk(BIOS_DEBUG, " F3xD8: %08x\n", dword);
Timothy Pearson83abd812015-06-08 19:35:06 -0500641 dword = pci_read_config32(dev, 0xdc);
Timothy Pearson38629f52015-09-05 18:46:54 -0500642 printk(BIOS_DEBUG, " F3xDC: %08x\n", dword);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000643 }
644}
645
Timothy Pearson730a0432015-10-16 13:51:51 -0500646static void waitCurrentPstate(u32 target_pstate) {
Timothy Pearson0122afb2015-07-30 14:07:15 -0500647 msr_t initial_msr = rdmsr(TSC_MSR);
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200648 msr_t pstate_msr = rdmsr(PS_STS_REG);
Timothy Pearson0122afb2015-07-30 14:07:15 -0500649 msr_t tsc_msr;
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200650 u8 timedout;
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000651
Timothy Pearson0122afb2015-07-30 14:07:15 -0500652 /* paranoia ? I fear when we run fixPsNbVidBeforeWR we can enter a
653 * P1 that is a copy of P0, therefore has the same NB DID but the
654 * TSC will count twice per tick, so we have to wait for twice the
655 * count to achieve the desired timeout. But I'm likely to
656 * misunderstand this...
657 */
658 u32 corrected_timeout = ((pstate_msr.lo==1)
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200659 && (!(rdmsr(PSTATE_1_MSR).lo & NB_DID_M_ON))) ?
Timothy Pearson0122afb2015-07-30 14:07:15 -0500660 WAIT_PSTATE_TIMEOUT*2 : WAIT_PSTATE_TIMEOUT;
661 msr_t timeout;
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000662
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200663 timeout.lo = initial_msr.lo + corrected_timeout;
Timothy Pearson0122afb2015-07-30 14:07:15 -0500664 timeout.hi = initial_msr.hi;
665 if ( (((u32)0xffffffff) - initial_msr.lo) < corrected_timeout ) {
666 timeout.hi++;
667 }
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000668
Timothy Pearson0122afb2015-07-30 14:07:15 -0500669 // assuming TSC ticks at 1.25 ns per tick (800 MHz)
670 do {
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200671 pstate_msr = rdmsr(PS_STS_REG);
Timothy Pearson0122afb2015-07-30 14:07:15 -0500672 tsc_msr = rdmsr(TSC_MSR);
673 timedout = (tsc_msr.hi > timeout.hi)
674 || ((tsc_msr.hi == timeout.hi) && (tsc_msr.lo > timeout.lo ));
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200675 } while ( (pstate_msr.lo != target_pstate) && (! timedout) );
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000676
Timothy Pearson0122afb2015-07-30 14:07:15 -0500677 if (pstate_msr.lo != target_pstate) {
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200678 msr_t limit_msr = rdmsr(PS_LIM_REG);
Timothy Pearson0122afb2015-07-30 14:07:15 -0500679 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",
680 cpuid_ebx(0x00000001) >> 24, target_pstate, pstate_msr.lo, limit_msr.hi, limit_msr.lo);
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000681
Timothy Pearson0122afb2015-07-30 14:07:15 -0500682 do { // should we just go on instead ?
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200683 pstate_msr = rdmsr(PS_STS_REG);
Elyes HAOUASa342f392018-10-17 10:56:26 +0200684 } while (pstate_msr.lo != target_pstate);
Timothy Pearson0122afb2015-07-30 14:07:15 -0500685 }
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000686}
687
688static void set_pstate(u32 nonBoostedPState) {
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600689 msr_t msr;
690 uint8_t skip_wait;
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000691
692 // Transition P0 for calling core.
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200693 msr = rdmsr(PS_CTL_REG);
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000694
695 msr.lo = nonBoostedPState;
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200696 wrmsr(PS_CTL_REG, msr);
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000697
Timothy Pearson730a0432015-10-16 13:51:51 -0500698 if (is_fam15h()) {
699 /* Do not wait for the first (even) set of cores to transition on Family 15h systems */
700 if ((cpuid_ebx(0x00000001) & 0x01000000))
701 skip_wait = 0;
702 else
703 skip_wait = 1;
704 } else {
705 skip_wait = 0;
706 }
707
708 if (!skip_wait) {
709 /* Wait for core to transition to P0 */
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200710 waitCurrentPstate(nonBoostedPState);
Timothy Pearson730a0432015-10-16 13:51:51 -0500711 }
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000712}
713
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000714static void UpdateSinglePlaneNbVid(void)
715{
716 u32 nbVid, cpuVid;
717 u8 i;
718 msr_t msr;
719
720 /* copy higher voltage (lower VID) of NBVID & CPUVID to both */
721 for (i = 0; i < 5; i++) {
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200722 msr = rdmsr(PSTATE_0_MSR + i);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000723 nbVid = (msr.lo & PS_CPU_VID_M_ON) >> PS_CPU_VID_SHFT;
724 cpuVid = (msr.lo & PS_NB_VID_M_ON) >> PS_NB_VID_SHFT;
725
726 if (nbVid != cpuVid) {
727 if (nbVid > cpuVid)
728 nbVid = cpuVid;
729
730 msr.lo = msr.lo & PS_BOTH_VID_OFF;
731 msr.lo = msr.lo | (u32) ((nbVid) << PS_NB_VID_SHFT);
732 msr.lo = msr.lo | (u32) ((nbVid) << PS_CPU_VID_SHFT);
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200733 wrmsr(PSTATE_0_MSR + i, msr);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000734 }
735 }
736}
737
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000738static void fixPsNbVidBeforeWR(u32 newNbVid, u32 coreid, u32 dev, u8 pviMode)
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600739{
740 msr_t msr;
741 u8 startup_pstate;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000742
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600743 /* This function sets NbVid before the warm reset.
744 * Get StartupPstate from MSRC001_0071.
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000745 * Read Pstate register pointed by [StartupPstate].
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600746 * and copy its content to P0 and P1 registers.
747 * Copy newNbVid to P0[NbVid].
748 * transition to P1 on all cores,
749 * then transition to P0 on core 0.
750 * Wait for MSRC001_0063[CurPstate] = 000b on core 0.
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200751 * see BKDG rev 3.48 2.4.2.9.1 BIOS NB COF and VID Configuration
752 * for SVI and Single-Plane PVI Systems
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600753 */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000754
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200755 msr = rdmsr(MSR_COFVID_STS);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000756 startup_pstate = (msr.hi >> (32 - 32)) & 0x07;
757
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000758 /* Copy startup pstate to P1 and P0 MSRs. Set the maxvid for
759 * this node in P0. Then transition to P1 for corex and P0
760 * for core0. These setting will be cleared by the warm reset
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000761 */
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200762 msr = rdmsr(PSTATE_0_MSR + startup_pstate);
763 wrmsr(PSTATE_1_MSR, msr);
764 wrmsr(PSTATE_0_MSR, msr);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000765
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200766 /* missing step 2 from BDKG , F3xDC[PstateMaxVal] =
767 * max(1,F3xDC[PstateMaxVal] ) because it would take
768 * synchronization between cores and we don't think
769 * PstatMaxVal is going to be 0 on cold reset anyway ?
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000770 */
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200771 if (!(pci_read_config32(dev, 0xdc) & (~PS_MAX_VAL_MASK))) {
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600772 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 +0000773 };
774
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000775 msr.lo &= ~0xFE000000; // clear nbvid
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000776 msr.lo |= (newNbVid << 25);
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200777 wrmsr(PSTATE_0_MSR, msr);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000778
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000779 if (pviMode) { /* single plane*/
780 UpdateSinglePlaneNbVid();
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200781 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000782
783 // Transition to P1 for all APs and P0 for core0.
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200784 set_pstate(1);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000785
786 if (coreid == 0) {
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200787 set_pstate(0);
Martin Rothe5f2d4c2017-07-23 16:07:31 -0600788 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000789
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000790 /* missing step 7 (restore PstateMax to 0 if needed) because
791 * we skipped step 2
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000792 */
793
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000794}
795
Xavi Drudis Ferranf7ef4212011-02-27 23:58:34 +0000796static u32 needs_NB_COF_VID_update(void)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000797{
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000798 u8 nb_cof_vid_update;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000799 u8 nodes;
800 u8 i;
801
Timothy Pearson730a0432015-10-16 13:51:51 -0500802 if (is_fam15h())
803 return 0;
804
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000805 /* If any node has nb_cof_vid_update set all nodes need an update. */
806 nodes = get_nodes();
807 nb_cof_vid_update = 0;
808 for (i = 0; i < nodes; i++) {
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200809 uint64_t cpuRev = mctGetLogicalCPUID(i);
810 u32 nbCofVidUpdateDefined = (cpuRev & (AMD_FAM10_LT_D));
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000811 if (nbCofVidUpdateDefined
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200812 && (pci_read_config32(NODE_PCI(i, 3), 0x1FC)
813 & NB_COF_VID_UPDATE_MASK)) {
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000814 nb_cof_vid_update = 1;
815 break;
816 }
817 }
Xavi Drudis Ferranf7ef4212011-02-27 23:58:34 +0000818 return nb_cof_vid_update;
819}
820
Xavi Drudis Ferran1f4fffb2011-02-28 00:00:51 +0000821static u32 init_fidvid_core(u32 nodeid, u32 coreid)
Xavi Drudis Ferranf7ef4212011-02-27 23:58:34 +0000822{
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200823 pci_devfn_t dev;
Xavi Drudis Ferranf7ef4212011-02-27 23:58:34 +0000824 u32 vid_max;
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000825 u32 fid_max = 0;
Xavi Drudis Ferranf7ef4212011-02-27 23:58:34 +0000826 u8 nb_cof_vid_update = needs_NB_COF_VID_update();
827 u8 pvimode;
828 u32 reg1fc;
Xavi Drudis Ferranf7ef4212011-02-27 23:58:34 +0000829
830 /* Steps 1-6 of BIOS NB COF and VID Configuration
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000831 * for SVI and Single-Plane PVI Systems. BKDG 2.4.2.9 #31116 rev 3.48
Xavi Drudis Ferranf7ef4212011-02-27 23:58:34 +0000832 */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000833 dev = NODE_PCI(nodeid, 3);
Timothy Pearson730a0432015-10-16 13:51:51 -0500834 if (is_fam15h())
835 pvimode = 0;
836 else
837 pvimode = pci_read_config32(dev, PW_CTL_MISC) & PVI_MODE;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000838 reg1fc = pci_read_config32(dev, 0x1FC);
839
840 if (nb_cof_vid_update) {
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200841 vid_max = (reg1fc & SINGLE_PLANE_NB_VID_MASK ) >> SINGLE_PLANE_NB_VID_SHIFT;
842 fid_max = (reg1fc & SINGLE_PLANE_NB_FID_MASK ) >> SINGLE_PLANE_NB_FID_SHIFT;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000843
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200844 if (!pvimode) { /* SVI, dual power plane */
845 vid_max = vid_max - ((reg1fc & DUAL_PLANE_NB_VID_OFF_MASK ) >> DUAL_PLANE_NB_VID_SHIFT );
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000846 fid_max = fid_max + ((reg1fc & DUAL_PLANE_NB_FID_OFF_MASK ) >> DUAL_PLANE_NB_FID_SHIFT );
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000847 }
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000848 /* write newNbVid to P-state Reg's NbVid always if NbVidUpdatedAll=1 */
Timothy Pearson730a0432015-10-16 13:51:51 -0500849 fixPsNbVidBeforeWR(vid_max, coreid, dev, pvimode);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000850
851 /* fid setup is handled by the BSP at the end. */
852
853 } else { /* ! nb_cof_vid_update */
854 /* Use max values */
855 if (pvimode)
856 UpdateSinglePlaneNbVid();
857 }
858
Xavi Drudis Ferran1f4fffb2011-02-28 00:00:51 +0000859 return ((nb_cof_vid_update << 16) | (fid_max << 8));
860
861}
862
Xavi Drudis Ferran6bdc83b2011-02-28 03:56:52 +0000863static void init_fidvid_ap(u32 apicid, u32 nodeid, u32 coreid)
Xavi Drudis Ferran1f4fffb2011-02-28 00:00:51 +0000864{
865 u32 send;
866
867 printk(BIOS_DEBUG, "FIDVID on AP: %02x\n", apicid);
868
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200869 send = init_fidvid_core(nodeid, coreid);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000870 send |= (apicid << 24); // ap apicid
871
872 // Send signal to BSP about this AP max fid
873 // This also indicates this AP is ready for warm reset (if required).
874 lapic_write(LAPIC_MSG_REG, send | F10_APSTATE_RESET);
875}
876
877static u32 calc_common_fid(u32 fid_packed, u32 fid_packed_new)
878{
879 u32 fidmax;
880 u32 fidmax_new;
881
882 fidmax = (fid_packed >> 8) & 0xFF;
883
884 fidmax_new = (fid_packed_new >> 8) & 0xFF;
885
886 if (fidmax > fidmax_new) {
887 fidmax = fidmax_new;
888 }
889
890 fid_packed &= 0xFF << 16;
891 fid_packed |= (fidmax << 8);
892 fid_packed |= fid_packed_new & (0xFF << 16); // set nb_cof_vid_update
893
894 return fid_packed;
895}
896
897static void init_fidvid_bsp_stage1(u32 ap_apicid, void *gp)
898{
899 u32 readback = 0;
900 u32 timeout = 1;
901
902 struct fidvid_st *fvp = gp;
903 int loop;
904
905 print_debug_fv("Wait for AP stage 1: ap_apicid = ", ap_apicid);
906
907 loop = 100000;
908 while (--loop > 0) {
909 if (lapic_remote_read(ap_apicid, LAPIC_MSG_REG, &readback) != 0)
910 continue;
Timothy Pearson730a0432015-10-16 13:51:51 -0500911 if (((readback & 0x3f) == F10_APSTATE_RESET)
912 || (is_fam15h() && ((readback & 0x3f) == F10_APSTATE_ASLEEP))) {
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000913 timeout = 0;
914 break; /* target ap is in stage 1 */
915 }
916 }
917
918 if (timeout) {
919 printk(BIOS_DEBUG, "%s: timed out reading from ap %02x\n",
920 __func__, ap_apicid);
921 return;
922 }
923
924 print_debug_fv("\treadback = ", readback);
925
926 fvp->common_fid = calc_common_fid(fvp->common_fid, readback);
927
928 print_debug_fv("\tcommon_fid(packed) = ", fvp->common_fid);
929
930}
931
Xavi Drudis Ferranc3132102011-02-28 03:49:28 +0000932static void fixPsNbVidAfterWR(u32 newNbVid, u8 NbVidUpdatedAll,u8 pviMode)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000933{
934 msr_t msr;
935 u8 i;
936 u8 StartupPstate;
937
Xavi Drudis Ferran26f97d22011-02-28 03:08:06 +0000938 /* BKDG 2.4.2.9.1 11-12
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200939 * This function copies newNbVid to NbVid bits in P-state
Xavi Drudis Ferran26f97d22011-02-28 03:08:06 +0000940 * Registers[4:0] if its NbDid bit=0, and IddValue!=0 in case of
941 * NbVidUpdatedAll =0 or copies newNbVid to NbVid bits in
942 * P-state Registers[4:0] if its IddValue!=0 in case of
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000943 * NbVidUpdatedAll=1. Then transition to StartPstate.
944 */
945
946 /* write newNbVid to P-state Reg's NbVid if its NbDid=0 */
947 for (i = 0; i < 5; i++) {
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200948 msr = rdmsr(PSTATE_0_MSR + i);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000949 /* NbDid (bit 22 of P-state Reg) == 0 or NbVidUpdatedAll = 1 */
Xavi Drudis Ferranc3132102011-02-28 03:49:28 +0000950 if ( (msr.hi & PS_IDD_VALUE_MASK)
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200951 && (msr.hi & PS_EN_MASK)
952 &&(((msr.lo & PS_NB_DID_MASK) == 0) || NbVidUpdatedAll)) {
Xavi Drudis Ferran26f97d22011-02-28 03:08:06 +0000953 msr.lo &= PS_NB_VID_M_OFF;
954 msr.lo |= (newNbVid & 0x7F) << PS_NB_VID_SHFT;
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200955 wrmsr(PSTATE_0_MSR + i, msr);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000956 }
957 }
958
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200959 /* Not documented. Would overwrite Nb_Vids just copied
960 * should we just update cpu_vid or nothing at all ?
Xavi Drudis Ferran26f97d22011-02-28 03:08:06 +0000961 */
962 if (pviMode) { //single plane
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200963 UpdateSinglePlaneNbVid();
Xavi Drudis Ferran26f97d22011-02-28 03:08:06 +0000964 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000965 /* For each core in the system, transition all cores to StartupPstate */
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200966 msr = rdmsr(MSR_COFVID_STS);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000967 StartupPstate = msr.hi & 0x07;
Xavi Drudis Ferranc3132102011-02-28 03:49:28 +0000968
Xavi Drudis Ferran26f97d22011-02-28 03:08:06 +0000969 /* Set and wait for StartupPstate to set. */
Elyes HAOUAS2765a892016-09-01 19:44:56 +0200970 set_pstate(StartupPstate);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000971
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000972}
973
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000974static void finalPstateChange(void)
975{
Martin Roth4c3ab732013-07-08 16:23:54 -0600976 /* Enable P0 on all cores for best performance.
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000977 * Linux can slow them down later if need be.
978 * It is safe since they will be in C1 halt
979 * most of the time anyway.
980 */
Xavi Drudis Ferran19245c92011-02-28 03:02:40 +0000981 set_pstate(0);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000982}
983
Damien Zammit75a3d1f2016-11-28 00:29:10 +1100984void init_fidvid_stage2(u32 apicid, u32 nodeid)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000985{
986 msr_t msr;
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200987 pci_devfn_t dev;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000988 u32 reg1fc;
989 u32 dtemp;
990 u32 nbvid;
Xavi Drudis Ferranf7ef4212011-02-27 23:58:34 +0000991 u8 nb_cof_vid_update = needs_NB_COF_VID_update();
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000992 u8 NbVidUpdateAll;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000993 u8 pvimode;
994
995 /* After warm reset finish the fid/vid setup for all cores. */
996
997 /* If any node has nb_cof_vid_update set all nodes need an update. */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000998
999 dev = NODE_PCI(nodeid, 3);
Timothy Pearson730a0432015-10-16 13:51:51 -05001000 if (is_fam15h())
1001 pvimode = 0;
1002 else
1003 pvimode = (pci_read_config32(dev, 0xA0) >> 8) & 1;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001004 reg1fc = pci_read_config32(dev, 0x1FC);
1005 nbvid = (reg1fc >> 7) & 0x7F;
1006 NbVidUpdateAll = (reg1fc >> 1) & 1;
1007
1008 if (nb_cof_vid_update) {
Xavi Drudis Ferran26f97d22011-02-28 03:08:06 +00001009 if (!pvimode) { /* SVI */
1010 nbvid = nbvid - ((reg1fc >> 17) & 0x1F);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001011 }
Xavi Drudis Ferran26f97d22011-02-28 03:08:06 +00001012 /* write newNbVid to P-state Reg's NbVid if its NbDid=0 */
1013 fixPsNbVidAfterWR(nbvid, NbVidUpdateAll,pvimode);
Martin Rothe5f2d4c2017-07-23 16:07:31 -06001014 } else { /* !nb_cof_vid_update */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001015 if (pvimode)
1016 UpdateSinglePlaneNbVid();
1017 }
1018 dtemp = pci_read_config32(dev, 0xA0);
1019 dtemp &= PLLLOCK_OFF;
1020 dtemp |= PLLLOCK_DFT_L;
1021 pci_write_config32(dev, 0xA0, dtemp);
1022
Elyes HAOUAS2765a892016-09-01 19:44:56 +02001023 dualPlaneOnly(dev);
1024 applyBoostFIDOffset(dev, nodeid);
1025 enableNbPState1(dev);
Xavi Drudis Ferran5bcedee2011-02-28 03:25:07 +00001026
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001027 finalPstateChange();
1028
Timothy Pearson730a0432015-10-16 13:51:51 -05001029 if (!is_fam15h()) {
1030 /* Set TSC to tick at the P0 ndfid rate */
Elyes HAOUAS400ce552018-10-12 10:54:30 +02001031 msr = rdmsr(HWCR_MSR);
Timothy Pearson730a0432015-10-16 13:51:51 -05001032 msr.lo |= 1 << 24;
Elyes HAOUAS400ce552018-10-12 10:54:30 +02001033 wrmsr(HWCR_MSR, msr);
Timothy Pearson730a0432015-10-16 13:51:51 -05001034 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001035}
1036
1037
Julius Wernercd49cce2019-03-05 16:53:33 -08001038#if CONFIG(SET_FIDVID_STORE_AP_APICID_AT_FIRST)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001039struct ap_apicid_st {
1040 u32 num;
1041 // it could use 256 bytes for 64 node quad core system
1042 u8 apicid[NODE_NUMS * 4];
1043};
1044
1045static void store_ap_apicid(unsigned ap_apicid, void *gp)
1046{
1047 struct ap_apicid_st *p = gp;
1048
1049 p->apicid[p->num++] = ap_apicid;
1050
1051}
1052#endif
1053
1054
Damien Zammit75a3d1f2016-11-28 00:29:10 +11001055int init_fidvid_bsp(u32 bsp_apicid, u32 nodes)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001056{
Julius Wernercd49cce2019-03-05 16:53:33 -08001057#if CONFIG(SET_FIDVID_STORE_AP_APICID_AT_FIRST)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001058 struct ap_apicid_st ap_apicidx;
1059 u32 i;
1060#endif
1061 struct fidvid_st fv;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001062
1063 printk(BIOS_DEBUG, "FIDVID on BSP, APIC_id: %02x\n", bsp_apicid);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001064
1065 /* Steps 1-6 of BIOS NB COF and VID Configuration
1066 * for SVI and Single-Plane PVI Systems.
1067 */
Timothy Pearson730a0432015-10-16 13:51:51 -05001068 fv.common_fid = init_fidvid_core(0, 0);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001069
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001070 print_debug_fv("BSP fid = ", fv.common_fid);
1071
Julius Wernercd49cce2019-03-05 16:53:33 -08001072#if CONFIG(SET_FIDVID_STORE_AP_APICID_AT_FIRST) && \
1073 !CONFIG(SET_FIDVID_CORE0_ONLY)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001074 /* For all APs (We know the APIC ID of all APs even when the APIC ID
1075 is lifted) remote read from AP LAPIC_MSG_REG about max fid.
1076 Then calculate the common max fid that can be used for all
1077 APs and BSP */
1078 ap_apicidx.num = 0;
1079
Timothy Pearson0122afb2015-07-30 14:07:15 -05001080 for_each_ap(bsp_apicid, CONFIG_SET_FIDVID_CORE_RANGE, -1, store_ap_apicid, &ap_apicidx);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001081
1082 for (i = 0; i < ap_apicidx.num; i++) {
1083 init_fidvid_bsp_stage1(ap_apicidx.apicid[i], &fv);
1084 }
1085#else
Julius Werner5d1f9a02019-03-07 17:07:26 -08001086 for_each_ap(bsp_apicid, CONFIG(SET_FIDVID_CORE0_ONLY), -1, init_fidvid_bsp_stage1, &fv);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001087#endif
1088
1089 print_debug_fv("common_fid = ", fv.common_fid);
1090
1091 if (fv.common_fid & (1 << 16)) { /* check nb_cof_vid_update */
1092
1093 // Enable the common fid and other settings.
1094 enable_fid_change((fv.common_fid >> 8) & 0x1F);
1095
1096 // nbfid change need warm reset, so reset at first
1097 return 1;
1098 }
1099
1100 return 0; // No FID/VID changes. Don't reset
1101}