blob: 452f7ce3fd111209ba25e4b894c0cb156c4fb3ab [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 */
13
Elyes HAOUAS20eaef02019-03-29 17:45:28 +010014#include <console/console.h>
Elyes HAOUAS400ce552018-10-12 10:54:30 +020015#include <cpu/amd/msr.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020016#include <device/pci_ops.h>
Elyes HAOUASb12ece92019-05-15 21:01:02 +020017#include <types.h>
18
Damien Zammit75a3d1f2016-11-28 00:29:10 +110019#include "init_cpus.h"
20
Julius Wernercd49cce2019-03-05 16:53:33 -080021#if CONFIG(HAVE_OPTION_TABLE)
Damien Zammit75a3d1f2016-11-28 00:29:10 +110022#include "option_table.h"
23#endif
24#include <pc80/mc146818rtc.h>
25
26#include <northbridge/amd/amdht/ht_wrapper.h>
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000027#include <northbridge/amd/amdht/AsPsDefs.h>
28#include <northbridge/amd/amdht/porting.h>
Damien Zammit75a3d1f2016-11-28 00:29:10 +110029#include <northbridge/amd/amdht/h3ncmn.h>
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000030
Nico Huber718c6fa2018-10-11 22:54:25 +020031#include <southbridge/amd/common/reset.h>
32
Julius Wernercd49cce2019-03-05 16:53:33 -080033#if CONFIG(SOUTHBRIDGE_AMD_SB700)
Timothy Pearson83abd812015-06-08 19:35:06 -050034#include <southbridge/amd/sb700/sb700.h>
35#endif
36
Julius Wernercd49cce2019-03-05 16:53:33 -080037#if CONFIG(SOUTHBRIDGE_AMD_SB800)
Timothy Pearson83abd812015-06-08 19:35:06 -050038#include <southbridge/amd/sb800/sb800.h>
39#endif
40
Kyösti Mälkkib98391c2017-07-13 13:14:16 +030041#include "cpu/amd/car/disable_cache_as_ram.c"
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000042
Julius Wernercd49cce2019-03-05 16:53:33 -080043#if CONFIG(PCI_IO_CFG_EXT)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000044static void set_EnableCf8ExtCfg(void)
45{
Elyes HAOUAS400ce552018-10-12 10:54:30 +020046 // set the NB_CFG_MSR[46]=1;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000047 msr_t msr;
48 msr = rdmsr(NB_CFG_MSR);
49 // EnableCf8ExtCfg: We need that to access CONFIG_PCI_IO_CFG_EXT 4K range
50 msr.hi |= (1 << (46 - 32));
51 wrmsr(NB_CFG_MSR, msr);
52}
53#else
54static void set_EnableCf8ExtCfg(void) { }
55#endif
56
Timothy Pearson0122afb2015-07-30 14:07:15 -050057// #define DEBUG_HT_SETUP 1
58// #define FAM10_AP_NODE_SEQUENTIAL_START 1
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000059
Timothy Pearson730a0432015-10-16 13:51:51 -050060uint32_t get_boot_apic_id(uint8_t node, uint32_t core) {
61 uint32_t ap_apicid;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000062
Timothy Pearson730a0432015-10-16 13:51:51 -050063 uint32_t nb_cfg_54;
64 uint32_t siblings;
65 uint32_t cores_found;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000066
Timothy Pearson730a0432015-10-16 13:51:51 -050067 uint8_t fam15h = 0;
Timothy Pearson1c4508e2015-09-05 17:50:29 -050068 uint8_t rev_gte_d = 0;
69 uint8_t dual_node = 0;
70 uint32_t f3xe8;
Timothy Pearson730a0432015-10-16 13:51:51 -050071 uint32_t family;
72 uint32_t model;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000073
Timothy Pearson730a0432015-10-16 13:51:51 -050074 uint32_t ApicIdCoreIdSize;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000075
76 /* Assume that all node are same stepping, otherwise we can use use
77 nb_cfg_54 from bsp for all nodes */
78 nb_cfg_54 = read_nb_cfg_54();
Timothy Pearson1c4508e2015-09-05 17:50:29 -050079 f3xe8 = pci_read_config32(NODE_PCI(0, 3), 0xe8);
80
Timothy Pearson730a0432015-10-16 13:51:51 -050081 family = model = cpuid_eax(0x80000001);
82 model = ((model & 0xf0000) >> 12) | ((model & 0xf0) >> 4);
83 family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);
84
85 if (family >= 0x6f) {
86 /* Family 15h or later */
87 fam15h = 1;
88 nb_cfg_54 = 1;
89 }
90
91 if ((model >= 0x8) || fam15h)
Timothy Pearson1c4508e2015-09-05 17:50:29 -050092 /* Revision D or later */
93 rev_gte_d = 1;
94
95 if (rev_gte_d)
96 /* Check for dual node capability */
97 if (f3xe8 & 0x20000000)
98 dual_node = 1;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000099
100 ApicIdCoreIdSize = (cpuid_ecx(0x80000008) >> 12 & 0xf);
101 if (ApicIdCoreIdSize) {
102 siblings = ((1 << ApicIdCoreIdSize) - 1);
103 } else {
104 siblings = 3; //quad core
105 }
106
Timothy Pearson730a0432015-10-16 13:51:51 -0500107 cores_found = get_core_num_in_bsp(node);
108 if (siblings > cores_found)
109 siblings = cores_found;
110
111 if (dual_node) {
112 ap_apicid = 0;
113 if (fam15h) {
114 ap_apicid |= ((node >> 1) & 0x3) << 5; /* Node ID */
115 ap_apicid |= ((node & 0x1) * (siblings + 1)) + core; /* Core ID */
116 } else {
117 if (nb_cfg_54) {
118 ap_apicid |= ((node >> 1) & 0x3) << 4; /* Node ID */
119 ap_apicid |= ((node & 0x1) * (siblings + 1)) + core; /* Core ID */
120 } else {
121 ap_apicid |= node & 0x3; /* Node ID */
122 ap_apicid |= (((node & 0x1) * (siblings + 1)) + core) << 4; /* Core ID */
123 }
124 }
125 } else {
126 if (fam15h) {
Timothy Pearson71f86412015-11-24 14:11:53 -0600127 ap_apicid = 0;
128 ap_apicid |= (node & 0x7) << 4; /* Node ID */
129 ap_apicid |= core & 0xf; /* Core ID */
Timothy Pearson730a0432015-10-16 13:51:51 -0500130 } else {
131 ap_apicid = node * (nb_cfg_54 ? (siblings + 1) : 1) +
132 core * (nb_cfg_54 ? 1 : 64);
133 }
134 }
135
Timothy Pearson71f86412015-11-24 14:11:53 -0600136 printk(BIOS_DEBUG, "%s: using %d as APIC ID for node %d, core %d\n", __func__, ap_apicid, node, core);
137
Timothy Pearson730a0432015-10-16 13:51:51 -0500138 return ap_apicid;
139}
140
141//core_range = 0 : all cores
142//core range = 1 : core 0 only
143//core range = 2 : cores other than core0
144
Timothy Pearson0122afb2015-07-30 14:07:15 -0500145static void for_each_ap(uint32_t bsp_apicid, uint32_t core_range, int8_t node,
146 process_ap_t process_ap, void *gp)
Timothy Pearson730a0432015-10-16 13:51:51 -0500147{
148 // here assume the OS don't change our apicid
149 u32 ap_apicid;
150
151 u32 nodes;
152 u32 disable_siblings;
153 u32 cores_found;
154 int i, j;
155
156 /* get_nodes define in ht_wrapper.c */
157 nodes = get_nodes();
158
Julius Wernercd49cce2019-03-05 16:53:33 -0800159 if (!CONFIG(LOGICAL_CPUS) ||
Paul Menzele0368b42019-01-11 11:34:54 +0100160 read_option(multi_core, 0) != 0) { // 0 means multi core
Timothy Pearson730a0432015-10-16 13:51:51 -0500161 disable_siblings = 1;
Paul Menzele0368b42019-01-11 11:34:54 +0100162 } else {
163 disable_siblings = 0;
164 }
Timothy Pearson730a0432015-10-16 13:51:51 -0500165
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000166 for (i = 0; i < nodes; i++) {
Timothy Pearson0122afb2015-07-30 14:07:15 -0500167 if ((node >= 0) && (i != node))
168 continue;
169
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000170 cores_found = get_core_num_in_bsp(i);
171
172 u32 jstart, jend;
173
174 if (core_range == 2) {
175 jstart = 1;
176 } else {
177 jstart = 0;
178 }
179
180 if (disable_siblings || (core_range == 1)) {
181 jend = 0;
182 } else {
183 jend = cores_found;
184 }
185
186 for (j = jstart; j <= jend; j++) {
Timothy Pearson730a0432015-10-16 13:51:51 -0500187 ap_apicid = get_boot_apic_id(i, j);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000188
Julius Wernercd49cce2019-03-05 16:53:33 -0800189#if CONFIG(ENABLE_APIC_EXT_ID) && (CONFIG_APIC_ID_OFFSET > 0)
190#if !CONFIG(LIFT_BSP_APIC_ID)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000191 if ((i != 0) || (j != 0)) /* except bsp */
192#endif
193 ap_apicid += CONFIG_APIC_ID_OFFSET;
194#endif
195
196 if (ap_apicid == bsp_apicid)
197 continue;
198
199 process_ap(ap_apicid, gp);
200
201 }
202 }
203}
204
205static inline int lapic_remote_read(int apicid, int reg, u32 *pvalue)
206{
207 int timeout;
208 u32 status;
209 int result;
210 lapic_wait_icr_idle();
211 lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
212 lapic_write(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4));
213
214/* Extra busy check compared to lapic.h */
215 timeout = 0;
216 do {
217 status = lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY;
218 } while (status == LAPIC_ICR_BUSY && timeout++ < 1000);
219
220 timeout = 0;
221 do {
222 status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK;
223 } while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000);
224
225 result = -1;
226
227 if (status == LAPIC_ICR_RR_VALID) {
228 *pvalue = lapic_read(LAPIC_RRR);
229 result = 0;
230 }
231 return result;
232}
233
Julius Wernercd49cce2019-03-05 16:53:33 -0800234#if CONFIG(SET_FIDVID)
Xavi Drudis Ferran6bdc83b2011-02-28 03:56:52 +0000235static void init_fidvid_ap(u32 apicid, u32 nodeid, u32 coreid);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000236#endif
237
Aaron Durbin75a62e72018-09-13 02:10:45 -0600238static __always_inline
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000239void print_apicid_nodeid_coreid(u32 apicid, struct node_core_id id,
240 const char *str)
241{
242 printk(BIOS_DEBUG,
243 "%s --- { APICID = %02x NODEID = %02x COREID = %02x} ---\n", str,
244 apicid, id.nodeid, id.coreid);
245}
246
Timothy Pearson730a0432015-10-16 13:51:51 -0500247uint32_t wait_cpu_state(uint32_t apicid, uint32_t state, uint32_t state2)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000248{
249 u32 readback = 0;
250 u32 timeout = 1;
251 int loop = 4000000;
252 while (--loop > 0) {
253 if (lapic_remote_read(apicid, LAPIC_MSG_REG, &readback) != 0)
254 continue;
Timothy Pearson730a0432015-10-16 13:51:51 -0500255 if ((readback & 0x3f) == state || (readback & 0x3f) == state2 || (readback & 0x3f) == F10_APSTATE_RESET) {
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000256 timeout = 0;
Elyes HAOUASd82be922016-07-28 18:58:27 +0200257 break; //target CPU is in stage started
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000258 }
259 }
260 if (timeout) {
261 if (readback) {
262 timeout = readback;
263 }
264 }
265
266 return timeout;
267}
268
269static void wait_ap_started(u32 ap_apicid, void *gp)
270{
271 u32 timeout;
Timothy Pearson730a0432015-10-16 13:51:51 -0500272 timeout = wait_cpu_state(ap_apicid, F10_APSTATE_STARTED, F10_APSTATE_ASLEEP);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000273 printk(BIOS_DEBUG, "* AP %02x", ap_apicid);
274 if (timeout) {
275 printk(BIOS_DEBUG, " timed out:%08x\n", timeout);
276 } else {
277 printk(BIOS_DEBUG, "started\n");
278 }
279}
280
281void wait_all_other_cores_started(u32 bsp_apicid)
282{
283 // all aps other than core0
284 printk(BIOS_DEBUG, "started ap apicid: ");
Timothy Pearson0122afb2015-07-30 14:07:15 -0500285 for_each_ap(bsp_apicid, 2, -1, wait_ap_started, (void *)0);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000286 printk(BIOS_DEBUG, "\n");
287}
288
289void allow_all_aps_stop(u32 bsp_apicid)
290{
291 /* Called by the BSP to indicate AP can stop */
292
293 /* FIXME Do APs use this? */
294
295 // allow aps to stop use 6 bits for state
296 lapic_write(LAPIC_MSG_REG, (bsp_apicid << 24) | F10_APSTATE_STOPPED);
297}
298
Timothy Pearsoncb1dec52015-11-24 14:12:02 -0600299static void wait_ap_stopped(u32 ap_apicid, void *gp)
300{
301 u32 timeout;
302 timeout = wait_cpu_state(ap_apicid, F10_APSTATE_ASLEEP, F10_APSTATE_ASLEEP);
303 printk(BIOS_DEBUG, "* AP %02x", ap_apicid);
304 if (timeout) {
305 printk(BIOS_DEBUG, " timed out:%08x\n", timeout);
306 } else {
307 printk(BIOS_DEBUG, "stopped\n");
308 }
309}
310
311void wait_all_other_cores_stopped(u32 bsp_apicid)
312{
313 // all aps other than core0
314 printk(BIOS_DEBUG, "stopped ap apicid: ");
315 for_each_ap(bsp_apicid, 2, -1, wait_ap_stopped, (void *)0);
316 printk(BIOS_DEBUG, "\n");
317}
318
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000319static void enable_apic_ext_id(u32 node)
320{
321 u32 val;
322
323 val = pci_read_config32(NODE_HT(node), 0x68);
324 val |= (HTTC_APIC_EXT_SPUR | HTTC_APIC_EXT_ID | HTTC_APIC_EXT_BRD_CST);
325 pci_write_config32(NODE_HT(node), 0x68, val);
326}
327
Timothy Pearson730a0432015-10-16 13:51:51 -0500328static void STOP_CAR_AND_CPU(uint8_t skip_sharedc_config, uint32_t apicid)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000329{
330 msr_t msr;
Timothy Pearson730a0432015-10-16 13:51:51 -0500331 uint32_t family;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000332
Timothy Pearson730a0432015-10-16 13:51:51 -0500333 family = amd_fam1x_cpu_family(); // inline
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000334
Timothy Pearson730a0432015-10-16 13:51:51 -0500335 if (family < 0x6f) {
336 /* Family 10h or earlier */
337
338 /* Disable L2 IC to L3 connection (Only for CAR) */
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200339 msr = rdmsr(BU_CFG2_MSR);
Timothy Pearson730a0432015-10-16 13:51:51 -0500340 msr.lo &= ~(1 << ClLinesToNbDis);
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200341 wrmsr(BU_CFG2_MSR, msr);
Timothy Pearson38508a02015-06-25 15:07:34 -0500342 } else {
343 /* Family 15h or later
344 * DRAM setup is delayed on Fam15 in order to prevent
345 * any DRAM access before ECC check bits are initialized.
346 * Each core also needs to have its initial DRAM map initialized
347 * before it is put to sleep, otherwise it will fail to wake
348 * in ramstage. To meet both of these goals, delay DRAM map
349 * setup until the last possible moment, where speculative
350 * memory access is highly unlikely before core halt...
351 */
352 if (!skip_sharedc_config) {
353 /* Enable memory access for first MBs using top_mem */
354 msr.hi = 0;
355 msr.lo = (CONFIG_RAMTOP + TOP_MEM_MASK) & (~TOP_MEM_MASK);
356 wrmsr(TOP_MEM, msr);
357 }
Timothy Pearson730a0432015-10-16 13:51:51 -0500358 }
359
Kyösti Mälkkib98391c2017-07-13 13:14:16 +0300360 disable_cache_as_ram_real(skip_sharedc_config); // inline
Timothy Pearson730a0432015-10-16 13:51:51 -0500361
362 /* Mark the core as sleeping */
363 lapic_write(LAPIC_MSG_REG, (apicid << 24) | F10_APSTATE_ASLEEP);
364
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000365 /* stop all cores except node0/core0 the bsp .... */
366 stop_this_cpu();
367}
368
Damien Zammit75a3d1f2016-11-28 00:29:10 +1100369u32 init_cpus(u32 cpu_init_detectedx, struct sys_info *sysinfo)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000370{
Timothy Pearson0f1553b2015-08-02 21:06:39 -0500371 uint32_t bsp_apicid = 0;
372 uint32_t apicid;
373 uint32_t dword;
Timothy Pearson730a0432015-10-16 13:51:51 -0500374 uint8_t set_mtrrs;
Timothy Pearson0f1553b2015-08-02 21:06:39 -0500375 uint8_t node_count;
Timothy Pearson0df70462015-11-24 14:11:58 -0600376 uint8_t fam15_bsp_core1_apicid;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000377 struct node_core_id id;
378
Kyösti Mälkki184a1172019-08-15 15:37:30 +0300379 /* Please refer to the calculations and explaination in cache_as_ram.inc
380 * before modifying these values */
Timothy Pearsonb5e46552015-06-02 13:47:36 -0500381 uint32_t max_ap_stack_region_size = CONFIG_MAX_CPUS * CONFIG_DCACHE_AP_STACK_SIZE;
Kyösti Mälkki184a1172019-08-15 15:37:30 +0300382 uint32_t max_bsp_stack_region_size = CONFIG_DCACHE_BSP_TOP_STACK_SIZE +
383 CONFIG_DCACHE_BSP_TOP_STACK_SLUSH;
384 uint32_t bsp_stack_region_upper_boundary = CONFIG_DCACHE_RAM_BASE +
385 CONFIG_DCACHE_RAM_SIZE;
386 uint32_t bsp_stack_region_lower_boundary = bsp_stack_region_upper_boundary -
387 max_bsp_stack_region_size;
388
389 void *lower_stack_region_boundary = (void *)(bsp_stack_region_lower_boundary -
390 max_ap_stack_region_size);
391
Timothy Pearsonb5e46552015-06-02 13:47:36 -0500392 if (((void*)(sysinfo + 1)) > lower_stack_region_boundary)
393 printk(BIOS_WARNING,
394 "sysinfo extends into stack region (sysinfo range: [%p,%p] lower stack region boundary: %p)\n",
395 sysinfo, sysinfo + 1, lower_stack_region_boundary);
396
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000397 /*
398 * already set early mtrr in cache_as_ram.inc
399 */
400
401 /* that is from initial apicid, we need nodeid and coreid
402 later */
403 id = get_node_core_id_x();
404
405 /* NB_CFG MSR is shared between cores, so we need make sure
406 core0 is done at first --- use wait_all_core0_started */
407 if (id.coreid == 0) {
Timothy Pearson0122afb2015-07-30 14:07:15 -0500408 /* Set InitApicIdCpuIdLo / EnableCf8ExtCfg on core0 only */
409 if (!is_fam15h())
410 set_apicid_cpuid_lo();
411 set_EnableCf8ExtCfg();
Julius Wernercd49cce2019-03-05 16:53:33 -0800412#if CONFIG(ENABLE_APIC_EXT_ID)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000413 enable_apic_ext_id(id.nodeid);
414#endif
415 }
416
417 enable_lapic();
418
Julius Wernercd49cce2019-03-05 16:53:33 -0800419#if CONFIG(ENABLE_APIC_EXT_ID) && (CONFIG_APIC_ID_OFFSET > 0)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000420 u32 initial_apicid = get_initial_apicid();
421
Julius Wernercd49cce2019-03-05 16:53:33 -0800422#if !CONFIG(LIFT_BSP_APIC_ID)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000423 if (initial_apicid != 0) // other than bsp
424#endif
425 {
Elyes HAOUASd6e96862016-08-21 10:12:15 +0200426 /* use initial APIC id to lift it */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000427 u32 dword = lapic_read(LAPIC_ID);
428 dword &= ~(0xff << 24);
429 dword |=
430 (((initial_apicid + CONFIG_APIC_ID_OFFSET) & 0xff) << 24);
431
432 lapic_write(LAPIC_ID, dword);
433 }
Julius Wernercd49cce2019-03-05 16:53:33 -0800434#if CONFIG(LIFT_BSP_APIC_ID)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000435 bsp_apicid += CONFIG_APIC_ID_OFFSET;
436#endif
437
438#endif
439
440 /* get the apicid, it may be lifted already */
441 apicid = lapicid();
442
443 // show our apicid, nodeid, and coreid
444 if (id.coreid == 0) {
445 if (id.nodeid != 0) //all core0 except bsp
446 print_apicid_nodeid_coreid(apicid, id, " core0: ");
447 } else { //all other cores
448 print_apicid_nodeid_coreid(apicid, id, " corex: ");
449 }
450
451 if (cpu_init_detectedx) {
452 print_apicid_nodeid_coreid(apicid, id,
453 "\n\n\nINIT detected from ");
454 printk(BIOS_DEBUG, "\nIssuing SOFT_RESET...\n");
455 soft_reset();
456 }
457
458 if (id.coreid == 0) {
459 if (!(warm_reset_detect(id.nodeid))) //FIXME: INIT is checked above but check for more resets?
460 distinguish_cpu_resets(id.nodeid); // Also indicates we are started
461 }
462 // Mark the core as started.
463 lapic_write(LAPIC_MSG_REG, (apicid << 24) | F10_APSTATE_STARTED);
Timothy Pearson0122afb2015-07-30 14:07:15 -0500464 printk(BIOS_DEBUG, "CPU APICID %02x start flag set\n", apicid);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000465
466 if (apicid != bsp_apicid) {
467 /* Setup each AP's cores MSRs.
468 * This happens after HTinit.
469 * The BSP runs this code in it's own path.
470 */
471 update_microcode(cpuid_eax(1));
Kyösti Mälkkif0a13ce2013-12-08 07:20:48 +0200472
Timothy Pearson730a0432015-10-16 13:51:51 -0500473 cpuSetAMDMSR(id.nodeid);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000474
Timothy Pearson0f1553b2015-08-02 21:06:39 -0500475 /* Set up HyperTransport probe filter support */
476 if (is_gt_rev_d()) {
477 dword = pci_read_config32(NODE_PCI(id.nodeid, 0), 0x60);
478 node_count = ((dword >> 4) & 0x7) + 1;
479
480 if (node_count > 1) {
481 msr_t msr = rdmsr(BU_CFG2_MSR);
482 msr.hi |= 1 << (42 - 32);
483 wrmsr(BU_CFG2_MSR, msr);
484 }
485 }
486
Julius Wernercd49cce2019-03-05 16:53:33 -0800487#if CONFIG(SET_FIDVID)
488#if CONFIG(LOGICAL_CPUS) && CONFIG(SET_FIDVID_CORE0_ONLY)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000489 // Run on all AP for proper FID/VID setup.
490 if (id.coreid == 0) // only need set fid for core0
491#endif
492 {
493 // check warm(bios) reset to call stage2 otherwise do stage1
494 if (warm_reset_detect(id.nodeid)) {
495 printk(BIOS_DEBUG,
496 "init_fidvid_stage2 apicid: %02x\n",
497 apicid);
498 init_fidvid_stage2(apicid, id.nodeid);
499 } else {
500 printk(BIOS_DEBUG,
501 "init_fidvid_ap(stage1) apicid: %02x\n",
502 apicid);
Xavi Drudis Ferran6bdc83b2011-02-28 03:56:52 +0000503 init_fidvid_ap(apicid, id.nodeid, id.coreid);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000504 }
505 }
506#endif
507
Timothy Pearson730a0432015-10-16 13:51:51 -0500508 if (is_fam15h()) {
509 /* core 1 on node 0 is special; to avoid corrupting the
510 * BSP do not alter MTRRs on that core */
Elyes HAOUASadc32352019-06-06 16:59:34 +0200511 fam15_bsp_core1_apicid = 1;
Julius Wernercd49cce2019-03-05 16:53:33 -0800512 if (CONFIG(ENABLE_APIC_EXT_ID) && (CONFIG_APIC_ID_OFFSET > 0))
Elyes HAOUASadc32352019-06-06 16:59:34 +0200513 fam15_bsp_core1_apicid += CONFIG_APIC_ID_OFFSET;
Timothy Pearson0df70462015-11-24 14:11:58 -0600514
515 if (apicid == fam15_bsp_core1_apicid)
Timothy Pearson730a0432015-10-16 13:51:51 -0500516 set_mtrrs = 0;
517 else
518 set_mtrrs = !!(apicid & 0x1);
519 } else {
520 set_mtrrs = 1;
521 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000522
Timothy Pearson730a0432015-10-16 13:51:51 -0500523 /* AP is ready, configure MTRRs and go to sleep */
524 if (set_mtrrs)
Kyösti Mälkki65cc5262016-06-19 20:38:41 +0300525 set_var_mtrr(0, 0x00000000, CACHE_TMP_RAMTOP, MTRR_TYPE_WRBACK);
Timothy Pearson730a0432015-10-16 13:51:51 -0500526
527 printk(BIOS_DEBUG, "Disabling CAR on AP %02x\n", apicid);
528 if (is_fam15h()) {
529 /* Only modify the MSRs on the odd cores (the last cores to finish booting) */
530 STOP_CAR_AND_CPU(!set_mtrrs, apicid);
531 } else {
532 /* Modify MSRs on all cores */
533 STOP_CAR_AND_CPU(0, apicid);
534 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000535
536 printk(BIOS_DEBUG,
537 "\nAP %02x should be halted but you are reading this....\n",
538 apicid);
539 }
540
541 return bsp_apicid;
542}
543
544static u32 is_core0_started(u32 nodeid)
545{
546 u32 htic;
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200547 pci_devfn_t device;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000548 device = NODE_PCI(nodeid, 0);
549 htic = pci_read_config32(device, HT_INIT_CONTROL);
550 htic &= HTIC_ColdR_Detect;
551 return htic;
552}
553
554void wait_all_core0_started(void)
555{
556 /* When core0 is started, it will distingush_cpu_resets
557 * So wait for that to finish */
558 u32 i;
559 u32 nodes = get_nodes();
560
561 printk(BIOS_DEBUG, "core0 started: ");
562 for (i = 1; i < nodes; i++) { // skip bsp, because it is running on bsp
563 while (!is_core0_started(i)) {
564 }
565 printk(BIOS_DEBUG, " %02x", i);
566 }
567 printk(BIOS_DEBUG, "\n");
568}
569
570#if CONFIG_MAX_PHYSICAL_CPUS > 1
571/**
572 * void start_node(u32 node)
573 *
574 * start the core0 in node, so it can generate HT packet to feature code.
575 *
576 * This function starts the AP nodes core0s. wait_all_core0_started() in
577 * romstage.c waits for all the AP to be finished before continuing
578 * system init.
579 */
580static void start_node(u8 node)
581{
582 u32 val;
583
584 /* Enable routing table */
585 printk(BIOS_DEBUG, "Start node %02x", node);
586
Julius Wernercd49cce2019-03-05 16:53:33 -0800587#if CONFIG(NORTHBRIDGE_AMD_AMDFAM10)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000588 /* For FAM10 support, we need to set Dram base/limit for the new node */
589 pci_write_config32(NODE_MP(node), 0x44, 0);
590 pci_write_config32(NODE_MP(node), 0x40, 3);
591#endif
592
593 /* Allow APs to make requests (ROM fetch) */
594 val = pci_read_config32(NODE_HT(node), 0x6c);
595 val &= ~(1 << 1);
596 pci_write_config32(NODE_HT(node), 0x6c, val);
597
598 printk(BIOS_DEBUG, " done.\n");
599}
600
601/**
602 * static void setup_remote_node(u32 node)
603 *
Martin Roth4c3ab732013-07-08 16:23:54 -0600604 * Copy the BSP Address Map to each AP.
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000605 */
606static void setup_remote_node(u8 node)
607{
608 /* There registers can be used with F1x114_x Address Map at the
609 same time, So must set them even 32 node */
610 static const u16 pci_reg[] = {
611 /* DRAM Base/Limits Registers */
612 0x44, 0x4c, 0x54, 0x5c, 0x64, 0x6c, 0x74, 0x7c,
613 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78,
614 0x144, 0x14c, 0x154, 0x15c, 0x164, 0x16c, 0x174, 0x17c,
615 0x140, 0x148, 0x150, 0x158, 0x160, 0x168, 0x170, 0x178,
616 /* MMIO Base/Limits Registers */
617 0x84, 0x8c, 0x94, 0x9c, 0xa4, 0xac, 0xb4, 0xbc,
618 0x80, 0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8,
619 /* IO Base/Limits Registers */
620 0xc4, 0xcc, 0xd4, 0xdc,
621 0xc0, 0xc8, 0xd0, 0xd8,
622 /* Configuration Map Registers */
623 0xe0, 0xe4, 0xe8, 0xec,
624 };
625 u16 i;
626
627 printk(BIOS_DEBUG, "setup_remote_node: %02x", node);
628
629 /* copy the default resource map from node 0 */
630 for (i = 0; i < ARRAY_SIZE(pci_reg); i++) {
631 u32 value;
632 u16 reg;
633 reg = pci_reg[i];
634 value = pci_read_config32(NODE_MP(0), reg);
635 pci_write_config32(NODE_MP(node), reg, value);
636
637 }
638 printk(BIOS_DEBUG, " done\n");
639}
640#endif /* CONFIG_MAX_PHYSICAL_CPUS > 1 */
641
Timothy Pearson0122afb2015-07-30 14:07:15 -0500642//it is running on core0 of node0
Damien Zammit75a3d1f2016-11-28 00:29:10 +1100643void start_other_cores(uint32_t bsp_apicid)
Timothy Pearson0122afb2015-07-30 14:07:15 -0500644{
645 u32 nodes;
646 u32 nodeid;
647
648 // disable multi_core
Paul Menzele0368b42019-01-11 11:34:54 +0100649 if (read_option(multi_core, 0) != 0) {
Timothy Pearson0122afb2015-07-30 14:07:15 -0500650 printk(BIOS_DEBUG, "Skip additional core init\n");
651 return;
652 }
653
654 nodes = get_nodes();
655
656 for (nodeid = 0; nodeid < nodes; nodeid++) {
657 u32 cores = get_core_num_in_bsp(nodeid);
658 printk(BIOS_DEBUG, "init node: %02x cores: %02x pass 1\n", nodeid, cores);
659 if (cores > 0) {
660 real_start_other_core(nodeid, cores);
661#ifdef FAM10_AP_NODE_SEQUENTIAL_START
662 printk(BIOS_DEBUG, "waiting for core start on node %d...\n", nodeid);
663 for_each_ap(bsp_apicid, 2, nodeid, wait_ap_started, (void *)0);
664 printk(BIOS_DEBUG, "...started\n");
665#endif
666 }
667 }
668}
669
Timothy Pearson730a0432015-10-16 13:51:51 -0500670static void AMD_Errata281(u8 node, uint64_t revision, u32 platform)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000671{
672 /* Workaround for Transaction Scheduling Conflict in
673 * Northbridge Cross Bar. Implement XCS Token adjustment
674 * for ganged links. Also, perform fix up for the mixed
675 * revision case.
676 */
677
678 u32 reg, val;
679 u8 i;
680 u8 mixed = 0;
681 u8 nodes = get_nodes();
682
683 if (platform & AMD_PTYPE_SVR) {
684 /* For each node we need to check for a "broken" node */
685 if (!(revision & (AMD_DR_B0 | AMD_DR_B1))) {
686 for (i = 0; i < nodes; i++) {
687 if (mctGetLogicalCPUID(i) &
688 (AMD_DR_B0 | AMD_DR_B1)) {
689 mixed = 1;
690 break;
691 }
692 }
693 }
694
695 if ((revision & (AMD_DR_B0 | AMD_DR_B1)) || mixed) {
696
697 /* F0X68[22:21] DsNpReqLmt0 = 01b */
698 val = pci_read_config32(NODE_PCI(node, 0), 0x68);
699 val &= ~0x00600000;
700 val |= 0x00200000;
701 pci_write_config32(NODE_PCI(node, 0), 0x68, val);
702
703 /* F3X6C */
704 val = pci_read_config32(NODE_PCI(node, 3), 0x6C);
705 val &= ~0x700780F7;
706 val |= 0x00010094;
707 pci_write_config32(NODE_PCI(node, 3), 0x6C, val);
708
709 /* F3X7C */
710 val = pci_read_config32(NODE_PCI(node, 3), 0x7C);
711 val &= ~0x707FFF1F;
712 val |= 0x00144514;
713 pci_write_config32(NODE_PCI(node, 3), 0x7C, val);
714
715 /* F3X144[3:0] RspTok = 0001b */
716 val = pci_read_config32(NODE_PCI(node, 3), 0x144);
717 val &= ~0x0000000F;
718 val |= 0x00000001;
719 pci_write_config32(NODE_PCI(node, 3), 0x144, val);
720
721 for (i = 0; i < 3; i++) {
722 reg = 0x148 + (i * 4);
723 val = pci_read_config32(NODE_PCI(node, 3), reg);
724 val &= ~0x000000FF;
725 val |= 0x000000DB;
726 pci_write_config32(NODE_PCI(node, 3), reg, val);
727 }
728 }
729 }
730}
731
732static void AMD_Errata298(void)
733{
734 /* Workaround for L2 Eviction May Occur during operation to
735 * set Accessed or dirty bit.
736 */
737
738 msr_t msr;
739 u8 i;
740 u8 affectedRev = 0;
741 u8 nodes = get_nodes();
742
743 /* For each core we need to check for a "broken" node */
744 for (i = 0; i < nodes; i++) {
745 if (mctGetLogicalCPUID(i) & (AMD_DR_B0 | AMD_DR_B1 | AMD_DR_B2)) {
746 affectedRev = 1;
747 break;
748 }
749 }
750
751 if (affectedRev) {
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200752 msr = rdmsr(HWCR_MSR);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000753 msr.lo |= 0x08; /* Set TlbCacheDis bit[3] */
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200754 wrmsr(HWCR_MSR, msr);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000755
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200756 msr = rdmsr(BU_CFG_MSR);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000757 msr.lo |= 0x02; /* Set TlbForceMemTypeUc bit[1] */
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200758 wrmsr(BU_CFG_MSR, msr);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000759
760 msr = rdmsr(OSVW_ID_Length);
761 msr.lo |= 0x01; /* OS Visible Workaround - MSR */
762 wrmsr(OSVW_ID_Length, msr);
763
764 msr = rdmsr(OSVW_Status);
765 msr.lo |= 0x01; /* OS Visible Workaround - MSR */
766 wrmsr(OSVW_Status, msr);
767 }
768
769 if (!affectedRev && (mctGetLogicalCPUID(0xFF) & AMD_DR_B3)) {
770 msr = rdmsr(OSVW_ID_Length);
771 msr.lo |= 0x01; /* OS Visible Workaround - MSR */
772 wrmsr(OSVW_ID_Length, msr);
773
774 }
775}
776
777static u32 get_platform_type(void)
778{
779 u32 ret = 0;
780
781 switch (SYSTEM_TYPE) {
782 case 1:
783 ret |= AMD_PTYPE_DSK;
784 break;
785 case 2:
786 ret |= AMD_PTYPE_MOB;
787 break;
788 case 0:
789 ret |= AMD_PTYPE_SVR;
790 break;
791 default:
792 break;
793 }
794
795 /* FIXME: add UMA support. */
796
797 /* All Fam10 are multi core */
798 ret |= AMD_PTYPE_MC;
799
800 return ret;
801}
802
803static void AMD_SetupPSIVID_d(u32 platform_type, u8 node)
804{
805 u32 dword;
806 int i;
807 msr_t msr;
808
809 if (platform_type & (AMD_PTYPE_MOB | AMD_PTYPE_DSK)) {
810
811 /* The following code sets the PSIVID to the lowest support P state
812 * assuming that the VID for the lowest power state is below
813 * the VDD voltage regulator threshold. (This also assumes that there
814 * is a Pstate lower than P0)
815 */
816
817 for (i = 4; i >= 0; i--) {
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200818 msr = rdmsr(PSTATE_0_MSR + i);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000819 /* Pstate valid? */
820 if (msr.hi & PS_EN_MASK) {
821 dword = pci_read_config32(NODE_PCI(i, 3), 0xA0);
822 dword &= ~0x7F;
823 dword |= (msr.lo >> 9) & 0x7F;
824 pci_write_config32(NODE_PCI(i, 3), 0xA0, dword);
825 break;
826 }
827 }
828 }
829}
830
831/**
832 * AMD_CpuFindCapability - Traverse PCI capability list to find host HT links.
833 * HT Phy operations are not valid on links that aren't present, so this
834 * prevents invalid accesses.
835 *
836 * Returns the offset of the link register.
837 */
Elyes HAOUAS6c9737b2018-07-08 12:30:02 +0200838static BOOL AMD_CpuFindCapability(u8 node, u8 cap_count, u8 *offset)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000839{
840 u32 reg;
841 u32 val;
842
843 /* get start of CPU HT Host Capabilities */
844 val = pci_read_config32(NODE_PCI(node, 0), 0x34);
845 val &= 0xFF; //reg offset of first link
846
847 cap_count++;
848
849 /* Traverse through the capabilities. */
850 do {
851 reg = pci_read_config32(NODE_PCI(node, 0), val);
852 /* Is the capability block a HyperTransport capability block? */
853 if ((reg & 0xFF) == 0x08) {
854 /* Is the HT capability block an HT Host Capability? */
855 if ((reg & 0xE0000000) == (1 << 29))
856 cap_count--;
857 }
858
859 if (cap_count)
860 val = (reg >> 8) & 0xFF; //update reg offset
861 } while (cap_count && val);
862
863 *offset = (u8) val;
864
865 /* If requested capability found val != 0 */
866 if (!cap_count)
867 return TRUE;
868 else
869 return FALSE;
870}
871
872/**
873 * AMD_checkLinkType - Compare desired link characteristics using a logical
874 * link type mask.
875 *
876 * Returns the link characteristic mask.
877 */
Timothy Pearsonf8549e82015-09-07 22:26:55 -0500878static u32 AMD_checkLinkType(u8 node, u8 regoff)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000879{
Timothy Pearson965704a2015-08-07 19:04:49 -0500880 uint32_t val;
881 uint32_t val2;
882 uint32_t linktype = 0;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000883
884 /* Check connect, init and coherency */
885 val = pci_read_config32(NODE_PCI(node, 0), regoff + 0x18);
886 val &= 0x1F;
887
888 if (val == 3)
889 linktype |= HTPHY_LINKTYPE_COHERENT;
890
891 if (val == 7)
892 linktype |= HTPHY_LINKTYPE_NONCOHERENT;
893
894 if (linktype) {
895 /* Check gen3 */
896 val = pci_read_config32(NODE_PCI(node, 0), regoff + 0x08);
Timothy Pearson965704a2015-08-07 19:04:49 -0500897 val = (val >> 8) & 0xf;
898 if (is_gt_rev_d()) {
899 val2 = pci_read_config32(NODE_PCI(node, 0), regoff + 0x1c);
900 val |= (val2 & 0x1) << 4;
901 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000902
Timothy Pearson965704a2015-08-07 19:04:49 -0500903 if (val > 6)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000904 linktype |= HTPHY_LINKTYPE_HT3;
905 else
906 linktype |= HTPHY_LINKTYPE_HT1;
907
908 /* Check ganged */
Timothy Pearsonf8549e82015-09-07 22:26:55 -0500909 val = pci_read_config32(NODE_PCI(node, 0), (((regoff - 0x80) / 0x20) << 2) + 0x170);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000910
911 if (val & 1)
912 linktype |= HTPHY_LINKTYPE_GANGED;
913 else
914 linktype |= HTPHY_LINKTYPE_UNGANGED;
915 }
Timothy Pearsone536a4d2015-08-02 21:31:17 -0500916
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000917 return linktype;
918}
919
920/**
921 * AMD_SetHtPhyRegister - Use the HT link's HT Phy portal registers to update
922 * a phy setting for that link.
923 */
924static void AMD_SetHtPhyRegister(u8 node, u8 link, u8 entry)
925{
926 u32 phyReg;
927 u32 phyBase;
928 u32 val;
929
930 /* Determine this link's portal */
931 if (link > 3)
932 link -= 4;
933
934 phyBase = ((u32) link << 3) | 0x180;
935
Timothy Pearson0122afb2015-07-30 14:07:15 -0500936 /* Determine if link is connected and abort if not */
937 if (!(pci_read_config32(NODE_PCI(node, 0), 0x98 + (link * 0x20)) & 0x1))
938 return;
939
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000940 /* Get the portal control register's initial value
941 * and update it to access the desired phy register
942 */
943 phyReg = pci_read_config32(NODE_PCI(node, 4), phyBase);
944
945 if (fam10_htphy_default[entry].htreg > 0x1FF) {
946 phyReg &= ~HTPHY_DIRECT_OFFSET_MASK;
947 phyReg |= HTPHY_DIRECT_MAP;
948 } else {
949 phyReg &= ~HTPHY_OFFSET_MASK;
950 }
951
952 /* Now get the current phy register data
953 * LinkPhyDone = 0, LinkPhyWrite = 0 is a read
954 */
955 phyReg |= fam10_htphy_default[entry].htreg;
956 pci_write_config32(NODE_PCI(node, 4), phyBase, phyReg);
957
958 do {
959 val = pci_read_config32(NODE_PCI(node, 4), phyBase);
960 } while (!(val & HTPHY_IS_COMPLETE_MASK));
961
962 /* Now we have the phy register data, apply the change */
963 val = pci_read_config32(NODE_PCI(node, 4), phyBase + 4);
964 val &= ~fam10_htphy_default[entry].mask;
965 val |= fam10_htphy_default[entry].data;
966 pci_write_config32(NODE_PCI(node, 4), phyBase + 4, val);
967
968 /* write it through the portal to the phy
969 * LinkPhyDone = 0, LinkPhyWrite = 1 is a write
970 */
971 phyReg |= HTPHY_WRITE_CMD;
972 pci_write_config32(NODE_PCI(node, 4), phyBase, phyReg);
973
974 do {
975 val = pci_read_config32(NODE_PCI(node, 4), phyBase);
976 } while (!(val & HTPHY_IS_COMPLETE_MASK));
977}
978
Timothy Pearson730a0432015-10-16 13:51:51 -0500979void cpuSetAMDMSR(uint8_t node_id)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000980{
981 /* This routine loads the CPU with default settings in fam10_msr_default
982 * table . It must be run after Cache-As-RAM has been enabled, and
983 * Hypertransport initialization has taken place. Also note
984 * that it is run on the current processor only, and only for the current
985 * processor core.
986 */
987 msr_t msr;
988 u8 i;
Timothy Pearson68130f52015-08-09 02:47:51 -0500989 uint8_t nvram;
Timothy Pearson730a0432015-10-16 13:51:51 -0500990 u32 platform;
991 uint64_t revision;
Timothy Pearson4e543d32015-11-24 14:12:07 -0600992 uint8_t enable_cpb;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000993
994 printk(BIOS_DEBUG, "cpuSetAMDMSR ");
995
996 revision = mctGetLogicalCPUID(0xFF);
997 platform = get_platform_type();
998
999 for (i = 0; i < ARRAY_SIZE(fam10_msr_default); i++) {
1000 if ((fam10_msr_default[i].revision & revision) &&
1001 (fam10_msr_default[i].platform & platform)) {
1002 msr = rdmsr(fam10_msr_default[i].msr);
1003 msr.hi &= ~fam10_msr_default[i].mask_hi;
1004 msr.hi |= fam10_msr_default[i].data_hi;
1005 msr.lo &= ~fam10_msr_default[i].mask_lo;
1006 msr.lo |= fam10_msr_default[i].data_lo;
1007 wrmsr(fam10_msr_default[i].msr, msr);
1008 }
1009 }
1010 AMD_Errata298();
1011
Timothy Pearson730a0432015-10-16 13:51:51 -05001012 /* Revision C0 and above */
1013 if (revision & AMD_OR_C0) {
Timothy Pearson68130f52015-08-09 02:47:51 -05001014 uint8_t enable_experimental_memory_speed_boost;
1015
1016 /* Check to see if cache partitioning is allowed */
1017 enable_experimental_memory_speed_boost = 0;
1018 if (get_option(&nvram, "experimental_memory_speed_boost") == CB_SUCCESS)
1019 enable_experimental_memory_speed_boost = !!nvram;
1020
Timothy Pearson730a0432015-10-16 13:51:51 -05001021 uint32_t f3x1fc = pci_read_config32(NODE_PCI(node_id, 3), 0x1fc);
Elyes HAOUAS400ce552018-10-12 10:54:30 +02001022 msr = rdmsr(FP_CFG_MSR);
Timothy Pearson730a0432015-10-16 13:51:51 -05001023 msr.hi &= ~(0x7 << (42-32)); /* DiDtCfg4 */
1024 msr.hi |= (((f3x1fc >> 17) & 0x7) << (42-32));
1025 msr.hi &= ~(0x1 << (41-32)); /* DiDtCfg5 */
1026 msr.hi |= (((f3x1fc >> 22) & 0x1) << (41-32));
1027 msr.hi &= ~(0x1 << (40-32)); /* DiDtCfg3 */
1028 msr.hi |= (((f3x1fc >> 16) & 0x1) << (40-32));
1029 msr.hi &= ~(0x7 << (32-32)); /* DiDtCfg1 (1) */
1030 msr.hi |= (((f3x1fc >> 11) & 0x7) << (32-32));
1031 msr.lo &= ~(0x1f << 27); /* DiDtCfg1 (2) */
1032 msr.lo |= (((f3x1fc >> 6) & 0x1f) << 27);
1033 msr.lo &= ~(0x3 << 25); /* DiDtCfg2 */
1034 msr.lo |= (((f3x1fc >> 14) & 0x3) << 25);
1035 msr.lo &= ~(0x1f << 18); /* DiDtCfg0 */
1036 msr.lo |= (((f3x1fc >> 1) & 0x1f) << 18);
1037 msr.lo &= ~(0x1 << 16); /* DiDtMode */
1038 msr.lo |= ((f3x1fc & 0x1) << 16);
Elyes HAOUAS400ce552018-10-12 10:54:30 +02001039 wrmsr(FP_CFG_MSR, msr);
Timothy Pearson68130f52015-08-09 02:47:51 -05001040
1041 if (enable_experimental_memory_speed_boost) {
Elyes HAOUAS400ce552018-10-12 10:54:30 +02001042 msr = rdmsr(BU_CFG3_MSR);
Timothy Pearson68130f52015-08-09 02:47:51 -05001043 msr.lo |= (0x3 << 20); /* PfcStrideMul = 0x3 */
Elyes HAOUAS400ce552018-10-12 10:54:30 +02001044 wrmsr(BU_CFG3_MSR, msr);
Timothy Pearson68130f52015-08-09 02:47:51 -05001045 }
Timothy Pearson730a0432015-10-16 13:51:51 -05001046 }
1047
Julius Wernercd49cce2019-03-05 16:53:33 -08001048#if CONFIG(SOUTHBRIDGE_AMD_SB700) || CONFIG(SOUTHBRIDGE_AMD_SB800)
Timothy Pearson83abd812015-06-08 19:35:06 -05001049 if (revision & (AMD_DR_GT_D0 | AMD_FAM15_ALL)) {
1050 /* Set up message triggered C1E */
Elyes HAOUAS400ce552018-10-12 10:54:30 +02001051 msr = rdmsr(MSR_INTPEND);
Timothy Pearson83abd812015-06-08 19:35:06 -05001052 msr.lo &= ~0xffff; /* IOMsgAddr = ACPI_PM_EVT_BLK */
1053 msr.lo |= ACPI_PM_EVT_BLK & 0xffff;
1054 msr.lo |= (0x1 << 29); /* BmStsClrOnHltEn = 1 */
1055 if (revision & AMD_DR_GT_D0) {
1056 msr.lo &= ~(0x1 << 28); /* C1eOnCmpHalt = 0 */
1057 msr.lo &= ~(0x1 << 27); /* SmiOnCmpHalt = 0 */
1058 }
Elyes HAOUAS400ce552018-10-12 10:54:30 +02001059 wrmsr(MSR_INTPEND, msr);
Timothy Pearson83abd812015-06-08 19:35:06 -05001060
Elyes HAOUAS400ce552018-10-12 10:54:30 +02001061 msr = rdmsr(HWCR_MSR);
Timothy Pearson83abd812015-06-08 19:35:06 -05001062 msr.lo |= (0x1 << 12); /* HltXSpCycEn = 1 */
Elyes HAOUAS400ce552018-10-12 10:54:30 +02001063 wrmsr(HWCR_MSR, msr);
Timothy Pearson83abd812015-06-08 19:35:06 -05001064 }
1065
1066 if (revision & (AMD_DR_Ex | AMD_FAM15_ALL)) {
Julius Wernercd49cce2019-03-05 16:53:33 -08001067 if (CONFIG(HAVE_ACPI_TABLES))
Elyes HAOUAS99f1d502019-05-25 11:47:56 +02001068 if ((get_option(&nvram, "cpu_c_states") == CB_SUCCESS) &&
1069 (nvram)) {
1070 /* Set up the C-state base address */
1071 msr_t c_state_addr_msr;
1072 c_state_addr_msr = rdmsr(MSR_CSTATE_ADDRESS);
1073 c_state_addr_msr.lo = ACPI_CPU_P_LVL2;
1074 wrmsr(MSR_CSTATE_ADDRESS, c_state_addr_msr);
1075 }
Timothy Pearson83abd812015-06-08 19:35:06 -05001076 }
Timothy Pearson83abd812015-06-08 19:35:06 -05001077#endif
1078
Timothy Pearson4e543d32015-11-24 14:12:07 -06001079 if (revision & AMD_FAM15_ALL) {
1080 enable_cpb = 1;
1081 if (get_option(&nvram, "cpu_core_boost") == CB_SUCCESS)
1082 enable_cpb = !!nvram;
1083
1084 if (!enable_cpb) {
1085 /* Disable Core Performance Boost */
Elyes HAOUAS400ce552018-10-12 10:54:30 +02001086 msr = rdmsr(HWCR_MSR);
Timothy Pearson4e543d32015-11-24 14:12:07 -06001087 msr.lo |= (0x1 << 25); /* CpbDis = 1 */
Elyes HAOUAS400ce552018-10-12 10:54:30 +02001088 wrmsr(HWCR_MSR, msr);
Timothy Pearson4e543d32015-11-24 14:12:07 -06001089 }
1090 }
1091
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001092 printk(BIOS_DEBUG, " done\n");
1093}
1094
1095static void cpuSetAMDPCI(u8 node)
1096{
1097 /* This routine loads the CPU with default settings in fam10_pci_default
1098 * table . It must be run after Cache-As-RAM has been enabled, and
1099 * Hypertransport initialization has taken place. Also note
1100 * that it is run for the first core on each node
1101 */
Timothy Pearson0122afb2015-07-30 14:07:15 -05001102 uint8_t i;
1103 uint8_t j;
Timothy Pearson730a0432015-10-16 13:51:51 -05001104 u32 platform;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001105 u32 val;
Timothy Pearson0122afb2015-07-30 14:07:15 -05001106 uint8_t offset;
Timothy Pearson83abd812015-06-08 19:35:06 -05001107 uint32_t dword;
Timothy Pearson730a0432015-10-16 13:51:51 -05001108 uint64_t revision;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001109
Timothy Pearson71b8f012015-08-07 23:59:17 -05001110 /* FIXME
1111 * This should be configurable
1112 */
1113 uint8_t sockets = 2;
1114 uint8_t sockets_populated = 2;
1115
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001116 printk(BIOS_DEBUG, "cpuSetAMDPCI %02d", node);
1117
1118 revision = mctGetLogicalCPUID(node);
1119 platform = get_platform_type();
1120
1121 AMD_SetupPSIVID_d(platform, node); /* Set PSIVID offset which is not table driven */
1122
1123 for (i = 0; i < ARRAY_SIZE(fam10_pci_default); i++) {
1124 if ((fam10_pci_default[i].revision & revision) &&
1125 (fam10_pci_default[i].platform & platform)) {
1126 val = pci_read_config32(NODE_PCI(node,
1127 fam10_pci_default[i].
1128 function),
1129 fam10_pci_default[i].offset);
1130 val &= ~fam10_pci_default[i].mask;
1131 val |= fam10_pci_default[i].data;
1132 pci_write_config32(NODE_PCI(node,
1133 fam10_pci_default[i].
1134 function),
1135 fam10_pci_default[i].offset, val);
1136 }
1137 }
1138
Timothy Pearson39495ba2015-11-24 14:11:47 -06001139 if (is_fam15h()) {
1140 if (CONFIG_CPU_SOCKET_TYPE == 0x14) {
1141 /* Socket C32 */
1142 dword = pci_read_config32(NODE_PCI(node, 0), 0x84);
1143 dword |= 0x1 << 13; /* LdtStopTriEn = 1 */
1144 pci_write_config32(NODE_PCI(node, 0), 0x84, dword);
1145
1146 dword = pci_read_config32(NODE_PCI(node, 0), 0xa4);
1147 dword |= 0x1 << 13; /* LdtStopTriEn = 1 */
1148 pci_write_config32(NODE_PCI(node, 0), 0xa4, dword);
1149
1150 dword = pci_read_config32(NODE_PCI(node, 0), 0xc4);
1151 dword |= 0x1 << 13; /* LdtStopTriEn = 1 */
1152 pci_write_config32(NODE_PCI(node, 0), 0xc4, dword);
1153
1154 dword = pci_read_config32(NODE_PCI(node, 0), 0xe4);
1155 dword |= 0x1 << 13; /* LdtStopTriEn = 1 */
1156 pci_write_config32(NODE_PCI(node, 0), 0xe4, dword);
1157 }
1158 else {
1159 /* Other socket (G34, etc.) */
1160 dword = pci_read_config32(NODE_PCI(node, 0), 0x84);
1161 dword &= ~(0x1 << 13); /* LdtStopTriEn = 0 */
1162 pci_write_config32(NODE_PCI(node, 0), 0x84, dword);
1163
1164 dword = pci_read_config32(NODE_PCI(node, 0), 0xa4);
1165 dword &= ~(0x1 << 13); /* LdtStopTriEn = 0 */
1166 pci_write_config32(NODE_PCI(node, 0), 0xa4, dword);
1167
1168 dword = pci_read_config32(NODE_PCI(node, 0), 0xc4);
1169 dword &= ~(0x1 << 13); /* LdtStopTriEn = 0 */
1170 pci_write_config32(NODE_PCI(node, 0), 0xc4, dword);
1171
1172 dword = pci_read_config32(NODE_PCI(node, 0), 0xe4);
1173 dword &= ~(0x1 << 13); /* LdtStopTriEn = 0 */
1174 pci_write_config32(NODE_PCI(node, 0), 0xe4, dword);
1175 }
1176 }
1177
Timothy Pearson0122afb2015-07-30 14:07:15 -05001178#ifdef DEBUG_HT_SETUP
1179 /* Dump link settings */
1180 for (i = 0; i < 4; i++) {
1181 for (j = 0; j < 4; j++) {
1182 printk(BIOS_DEBUG, "Node %d link %d: type register: %08x control register: %08x extended control sublink 0: %08x 1: %08x\n", i, j,
1183 pci_read_config32(NODE_PCI(i, 0), 0x98 + (j * 0x20)), pci_read_config32(NODE_PCI(i, 0), 0x84 + (j * 0x20)),
1184 pci_read_config32(NODE_PCI(i, 0), 0x170 + (j * 0x4)), pci_read_config32(NODE_PCI(i, 0), 0x180 + (j * 0x4)));
1185 }
1186 }
1187#endif
1188
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001189 for (i = 0; i < ARRAY_SIZE(fam10_htphy_default); i++) {
1190 if ((fam10_htphy_default[i].revision & revision) &&
1191 (fam10_htphy_default[i].platform & platform)) {
1192 /* HT Phy settings either apply to both sublinks or have
1193 * separate registers for sublink zero and one, so there
1194 * will be two table entries. So, here we only loop
1195 * through the sublink zeros in function zero.
1196 */
1197 for (j = 0; j < 4; j++) {
1198 if (AMD_CpuFindCapability(node, j, &offset)) {
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001199 if (AMD_checkLinkType(node, offset)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001200 & fam10_htphy_default[i].linktype) {
1201 AMD_SetHtPhyRegister(node, j,
1202 i);
1203 }
1204 } else {
1205 /* No more capabilities,
1206 * link not present
1207 */
1208 break;
1209 }
1210 }
1211 }
1212 }
1213
1214 /* FIXME: add UMA support and programXbarToSriReg(); */
1215
1216 AMD_Errata281(node, revision, platform);
1217
1218 /* FIXME: if the dct phy doesn't init correct it needs to reset.
1219 if (revision & (AMD_DR_B2 | AMD_DR_B3))
1220 dctPhyDiag(); */
1221
Timothy Pearson83abd812015-06-08 19:35:06 -05001222 if (revision & (AMD_DR_GT_D0 | AMD_FAM15_ALL)) {
1223 /* Set up message triggered C1E */
1224 dword = pci_read_config32(NODE_PCI(node, 3), 0xd4);
1225 dword &= ~(0x1 << 14); /* CacheFlushImmOnAllHalt = !is_fam15h() */
1226 dword |= (is_fam15h()?0:1) << 14;
1227 pci_write_config32(NODE_PCI(node, 3), 0xd4, dword);
1228
1229 dword = pci_read_config32(NODE_PCI(node, 3), 0xdc);
1230 dword |= 0x1 << 26; /* IgnCpuPrbEn = 1 */
1231 dword &= ~(0x7f << 19); /* CacheFlushOnHaltTmr = 0x28 */
1232 dword |= 0x28 << 19;
1233 dword |= 0x7 << 16; /* CacheFlushOnHaltCtl = 0x7 */
1234 pci_write_config32(NODE_PCI(node, 3), 0xdc, dword);
1235
1236 dword = pci_read_config32(NODE_PCI(node, 3), 0xa0);
1237 dword |= 0x1 << 10; /* IdleExitEn = 1 */
1238 pci_write_config32(NODE_PCI(node, 3), 0xa0, dword);
1239
1240 if (revision & AMD_DR_GT_D0) {
1241 dword = pci_read_config32(NODE_PCI(node, 3), 0x188);
1242 dword |= 0x1 << 4; /* EnStpGntOnFlushMaskWakeup = 1 */
1243 pci_write_config32(NODE_PCI(node, 3), 0x188, dword);
1244 } else {
1245 dword = pci_read_config32(NODE_PCI(node, 4), 0x128);
1246 dword &= ~(0x1 << 31); /* CstateMsgDis = 0 */
1247 pci_write_config32(NODE_PCI(node, 4), 0x128, dword);
1248 }
1249
1250 dword = pci_read_config32(NODE_PCI(node, 3), 0xd4);
1251 dword |= 0x1 << 13; /* MTC1eEn = 1 */
1252 pci_write_config32(NODE_PCI(node, 3), 0xd4, dword);
1253 }
1254
Timothy Pearson965704a2015-08-07 19:04:49 -05001255 if (revision & AMD_FAM15_ALL) {
1256 uint32_t f5x80;
1257 uint8_t cu_enabled;
1258 uint8_t compute_unit_count = 0;
1259 uint8_t compute_unit_buffer_count;
1260
Timothy Pearson71b8f012015-08-07 23:59:17 -05001261 uint32_t f3xe8;
1262 uint8_t dual_node = 0;
1263
1264 f3xe8 = pci_read_config32(NODE_PCI(0, 3), 0xe8);
1265
1266 /* Check for dual node capability */
1267 if (f3xe8 & 0x20000000)
1268 dual_node = 1;
1269
Timothy Pearson965704a2015-08-07 19:04:49 -05001270 /* Determine the number of active compute units on this node */
1271 f5x80 = pci_read_config32(NODE_PCI(node, 5), 0x80);
1272 cu_enabled = f5x80 & 0xf;
1273 if (cu_enabled == 0x1)
1274 compute_unit_count = 1;
1275 if (cu_enabled == 0x3)
1276 compute_unit_count = 2;
1277 if (cu_enabled == 0x7)
1278 compute_unit_count = 3;
1279 if (cu_enabled == 0xf)
1280 compute_unit_count = 4;
1281
1282 if (compute_unit_count == 1)
1283 compute_unit_buffer_count = 0x1c;
1284 else if (compute_unit_count == 2)
1285 compute_unit_buffer_count = 0x18;
1286 else if (compute_unit_count == 3)
1287 compute_unit_buffer_count = 0x14;
1288 else
1289 compute_unit_buffer_count = 0x10;
1290
1291 dword = pci_read_config32(NODE_PCI(node, 3), 0x1a0);
1292 dword &= ~(0x1f << 4); /* L3FreeListCBC = compute_unit_buffer_count */
1293 dword |= (compute_unit_buffer_count << 4);
1294 pci_write_config32(NODE_PCI(node, 3), 0x1a0, dword);
Timothy Pearson71b8f012015-08-07 23:59:17 -05001295
Timothy Pearsona52d5d12015-08-08 20:30:36 -05001296 uint8_t link;
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001297 uint8_t link_real;
Timothy Pearsona52d5d12015-08-08 20:30:36 -05001298 uint8_t ganged;
1299 uint8_t iolink;
1300 uint8_t probe_filter_enabled = !!dual_node;
1301
1302 /* Set up the Link Base Channel Buffer Count */
1303 uint8_t isoc_rsp_data;
1304 uint8_t isoc_np_req_data;
1305 uint8_t isoc_rsp_cmd;
1306 uint8_t isoc_preq;
1307 uint8_t isoc_np_req_cmd;
1308 uint8_t free_data;
1309 uint8_t free_cmd;
1310 uint8_t rsp_data;
1311 uint8_t np_req_data;
1312 uint8_t probe_cmd;
1313 uint8_t rsp_cmd;
1314 uint8_t preq;
1315 uint8_t np_req_cmd;
1316
1317 /* Common settings for all links and system configurations */
1318 isoc_rsp_data = 0;
1319 isoc_np_req_data = 0;
1320 isoc_rsp_cmd = 0;
1321 isoc_preq = 0;
1322 isoc_np_req_cmd = 1;
1323 free_cmd = 8;
1324
1325 for (link = 0; link < 4; link++) {
1326 if (AMD_CpuFindCapability(node, link, &offset)) {
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001327 link_real = (offset - 0x80) / 0x20;
1328 ganged = !!(pci_read_config32(NODE_PCI(node, 0), (link_real << 2) + 0x170) & 0x1);
1329 iolink = !!(AMD_checkLinkType(node, offset) & HTPHY_LINKTYPE_NONCOHERENT);
Timothy Pearsona52d5d12015-08-08 20:30:36 -05001330
1331 if (!iolink && ganged) {
1332 if (probe_filter_enabled) {
1333 free_data = 0;
1334 rsp_data = 3;
1335 np_req_data = 3;
1336 probe_cmd = 4;
1337 rsp_cmd = 9;
1338 preq = 2;
1339 np_req_cmd = 8;
1340 } else {
1341 free_data = 0;
1342 rsp_data = 3;
1343 np_req_data = 3;
1344 probe_cmd = 8;
1345 rsp_cmd = 9;
1346 preq = 2;
1347 np_req_cmd = 4;
1348 }
1349 } else if (!iolink && !ganged) {
1350 if (probe_filter_enabled) {
1351 free_data = 0;
1352 rsp_data = 3;
1353 np_req_data = 3;
1354 probe_cmd = 4;
1355 rsp_cmd = 9;
1356 preq = 2;
1357 np_req_cmd = 8;
1358 } else {
1359 free_data = 0;
1360 rsp_data = 3;
1361 np_req_data = 3;
1362 probe_cmd = 8;
1363 rsp_cmd = 9;
1364 preq = 2;
1365 np_req_cmd = 4;
1366 }
1367 } else if (iolink && ganged) {
1368 free_data = 0;
1369 rsp_data = 1;
1370 np_req_data = 0;
1371 probe_cmd = 0;
1372 rsp_cmd = 2;
1373 preq = 7;
1374 np_req_cmd = 14;
1375 } else {
1376 /* FIXME
1377 * This is an educated guess as the BKDG does not specify
1378 * the appropriate buffer counts for this case!
1379 */
1380 free_data = 1;
1381 rsp_data = 1;
1382 np_req_data = 1;
1383 probe_cmd = 0;
1384 rsp_cmd = 2;
1385 preq = 4;
1386 np_req_cmd = 12;
1387 }
1388
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001389 dword = pci_read_config32(NODE_PCI(node, 0), (link_real * 0x20) + 0x94);
Timothy Pearsona52d5d12015-08-08 20:30:36 -05001390 dword &= ~(0x3 << 27); /* IsocRspData = isoc_rsp_data */
1391 dword |= ((isoc_rsp_data & 0x3) << 27);
1392 dword &= ~(0x3 << 25); /* IsocNpReqData = isoc_np_req_data */
1393 dword |= ((isoc_np_req_data & 0x3) << 25);
1394 dword &= ~(0x7 << 22); /* IsocRspCmd = isoc_rsp_cmd */
1395 dword |= ((isoc_rsp_cmd & 0x7) << 22);
1396 dword &= ~(0x7 << 19); /* IsocPReq = isoc_preq */
1397 dword |= ((isoc_preq & 0x7) << 19);
1398 dword &= ~(0x7 << 16); /* IsocNpReqCmd = isoc_np_req_cmd */
1399 dword |= ((isoc_np_req_cmd & 0x7) << 16);
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001400 pci_write_config32(NODE_PCI(node, 0), (link_real * 0x20) + 0x94, dword);
Timothy Pearsona52d5d12015-08-08 20:30:36 -05001401
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001402 dword = pci_read_config32(NODE_PCI(node, 0), (link_real * 0x20) + 0x90);
Timothy Pearsona52d5d12015-08-08 20:30:36 -05001403 dword &= ~(0x1 << 31); /* LockBc = 0x1 */
1404 dword |= ((0x1 & 0x1) << 31);
1405 dword &= ~(0x7 << 25); /* FreeData = free_data */
1406 dword |= ((free_data & 0x7) << 25);
1407 dword &= ~(0x1f << 20); /* FreeCmd = free_cmd */
1408 dword |= ((free_cmd & 0x1f) << 20);
1409 dword &= ~(0x3 << 18); /* RspData = rsp_data */
1410 dword |= ((rsp_data & 0x3) << 18);
1411 dword &= ~(0x3 << 16); /* NpReqData = np_req_data */
1412 dword |= ((np_req_data & 0x3) << 16);
1413 dword &= ~(0xf << 12); /* ProbeCmd = probe_cmd */
1414 dword |= ((probe_cmd & 0xf) << 12);
1415 dword &= ~(0xf << 8); /* RspCmd = rsp_cmd */
1416 dword |= ((rsp_cmd & 0xf) << 8);
1417 dword &= ~(0x7 << 5); /* PReq = preq */
1418 dword |= ((preq & 0x7) << 5);
1419 dword &= ~(0x1f << 0); /* NpReqCmd = np_req_cmd */
1420 dword |= ((np_req_cmd & 0x1f) << 0);
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001421 pci_write_config32(NODE_PCI(node, 0), (link_real * 0x20) + 0x90, dword);
Timothy Pearsona52d5d12015-08-08 20:30:36 -05001422 }
1423 }
1424
Timothy Pearson71b8f012015-08-07 23:59:17 -05001425 /* Set up the Link to XCS Token Counts */
1426 uint8_t isoc_rsp_tok_1;
1427 uint8_t isoc_preq_tok_1;
1428 uint8_t isoc_req_tok_1;
1429 uint8_t probe_tok_1;
1430 uint8_t rsp_tok_1;
1431 uint8_t preq_tok_1;
1432 uint8_t req_tok_1;
1433 uint8_t isoc_rsp_tok_0;
1434 uint8_t isoc_preq_tok_0;
1435 uint8_t isoc_req_tok_0;
1436 uint8_t free_tokens;
1437 uint8_t probe_tok_0;
1438 uint8_t rsp_tok_0;
1439 uint8_t preq_tok_0;
1440 uint8_t req_tok_0;
1441
Timothy Pearson71b8f012015-08-07 23:59:17 -05001442 for (link = 0; link < 4; link++) {
1443 if (AMD_CpuFindCapability(node, link, &offset)) {
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001444 link_real = (offset - 0x80) / 0x20;
1445 ganged = !!(pci_read_config32(NODE_PCI(node, 0), (link_real << 2) + 0x170) & 0x1);
1446 iolink = !!(AMD_checkLinkType(node, offset) & HTPHY_LINKTYPE_NONCOHERENT);
Timothy Pearson71b8f012015-08-07 23:59:17 -05001447
1448 /* Set defaults */
1449 isoc_rsp_tok_1 = 0;
1450 isoc_preq_tok_1 = 0;
1451 isoc_req_tok_1 = 0;
1452 probe_tok_1 = !ganged;
1453 rsp_tok_1 = !ganged;
1454 preq_tok_1 = !ganged;
1455 req_tok_1 = !ganged;
1456 isoc_rsp_tok_0 = 0;
1457 isoc_preq_tok_0 = 0;
1458 isoc_req_tok_0 = 0;
1459 free_tokens = 0;
1460 probe_tok_0 = ((ganged)?2:1);
1461 rsp_tok_0 = ((ganged)?2:1);
1462 preq_tok_0 = ((ganged)?2:1);
1463 req_tok_0 = ((ganged)?2:1);
1464
1465 if (!iolink && ganged) {
1466 if (!dual_node) {
1467 isoc_rsp_tok_1 = 0;
1468 isoc_preq_tok_1 = 0;
1469 isoc_req_tok_1 = 0;
1470 probe_tok_1 = 0;
1471 rsp_tok_1 = 0;
1472 preq_tok_1 = 0;
1473 req_tok_1 = 0;
1474 isoc_rsp_tok_0 = 0;
1475 isoc_preq_tok_0 = 0;
1476 isoc_req_tok_0 = 1;
1477 free_tokens = 3;
1478 probe_tok_0 = 2;
1479 rsp_tok_0 = 2;
1480 preq_tok_0 = 2;
1481 req_tok_0 = 2;
1482 } else {
1483 if ((sockets == 1)
1484 || ((sockets == 2) && (sockets_populated == 1))) {
1485 isoc_rsp_tok_1 = 0;
1486 isoc_preq_tok_1 = 0;
1487 isoc_req_tok_1 = 0;
1488 probe_tok_1 = 0;
1489 rsp_tok_1 = 0;
1490 preq_tok_1 = 0;
1491 req_tok_1 = 0;
1492 isoc_rsp_tok_0 = 0;
1493 isoc_preq_tok_0 = 0;
1494 isoc_req_tok_0 = 1;
1495 free_tokens = 0;
1496 probe_tok_0 = 2;
1497 rsp_tok_0 = 2;
1498 preq_tok_0 = 2;
1499 req_tok_0 = 2;
1500 } else if (((sockets == 2) && (sockets_populated == 2))
1501 || ((sockets == 4) && (sockets_populated == 2))) {
1502 isoc_rsp_tok_1 = 0;
1503 isoc_preq_tok_1 = 0;
1504 isoc_req_tok_1 = 0;
1505 probe_tok_1 = 0;
1506 rsp_tok_1 = 0;
1507 preq_tok_1 = 0;
1508 req_tok_1 = 0;
1509 isoc_rsp_tok_0 = 0;
1510 isoc_preq_tok_0 = 0;
1511 isoc_req_tok_0 = 1;
1512 free_tokens = 0;
1513 probe_tok_0 = 1;
1514 rsp_tok_0 = 2;
1515 preq_tok_0 = 2;
1516 req_tok_0 = 2;
1517 } else if ((sockets == 4) && (sockets_populated == 4)) {
1518 isoc_rsp_tok_1 = 0;
1519 isoc_preq_tok_1 = 0;
1520 isoc_req_tok_1 = 0;
1521 probe_tok_1 = 0;
1522 rsp_tok_1 = 0;
1523 preq_tok_1 = 0;
1524 req_tok_1 = 0;
1525 isoc_rsp_tok_0 = 0;
1526 isoc_preq_tok_0 = 0;
1527 isoc_req_tok_0 = 1;
1528 free_tokens = 0;
1529 probe_tok_0 = 2;
1530 rsp_tok_0 = 1;
1531 preq_tok_0 = 1;
1532 req_tok_0 = 2;
1533 }
1534 }
1535 } else if (!iolink && !ganged) {
1536 if ((sockets == 1)
1537 || ((sockets == 2) && (sockets_populated == 1))) {
1538 if (probe_filter_enabled) {
1539 isoc_rsp_tok_1 = 0;
1540 isoc_preq_tok_1 = 0;
1541 isoc_req_tok_1 = 0;
1542 probe_tok_1 = 1;
1543 rsp_tok_1 = 1;
1544 preq_tok_1 = 1;
1545 req_tok_1 = 1;
1546 isoc_rsp_tok_0 = 0;
1547 isoc_preq_tok_0 = 0;
1548 isoc_req_tok_0 = 1;
1549 free_tokens = 0;
1550 probe_tok_0 = 1;
1551 rsp_tok_0 = 2;
1552 preq_tok_0 = 1;
1553 req_tok_0 = 1;
1554 } else {
1555 isoc_rsp_tok_1 = 0;
1556 isoc_preq_tok_1 = 0;
1557 isoc_req_tok_1 = 0;
1558 probe_tok_1 = 1;
1559 rsp_tok_1 = 1;
1560 preq_tok_1 = 1;
1561 req_tok_1 = 1;
1562 isoc_rsp_tok_0 = 0;
1563 isoc_preq_tok_0 = 0;
1564 isoc_req_tok_0 = 1;
1565 free_tokens = 0;
1566 probe_tok_0 = 1;
1567 rsp_tok_0 = 1;
1568 preq_tok_0 = 1;
1569 req_tok_0 = 1;
1570 }
1571 } else if ((sockets == 2) && (sockets_populated == 2)) {
1572 isoc_rsp_tok_1 = 0;
1573 isoc_preq_tok_1 = 0;
1574 isoc_req_tok_1 = 1;
1575 probe_tok_1 = 1;
1576 rsp_tok_1 = 1;
1577 preq_tok_1 = 1;
1578 req_tok_1 = 1;
1579 isoc_rsp_tok_0 = 0;
1580 isoc_preq_tok_0 = 0;
1581 isoc_req_tok_0 = 1;
1582 free_tokens = 2;
1583 probe_tok_0 = 1;
1584 rsp_tok_0 = 1;
1585 preq_tok_0 = 1;
1586 req_tok_0 = 1;
1587 } else if ((sockets == 4) && (sockets_populated == 2)) {
1588 isoc_rsp_tok_1 = 0;
1589 isoc_preq_tok_1 = 0;
1590 isoc_req_tok_1 = 1;
1591 probe_tok_1 = 1;
1592 rsp_tok_1 = 1;
1593 preq_tok_1 = 1;
1594 req_tok_1 = 1;
1595 isoc_rsp_tok_0 = 0;
1596 isoc_preq_tok_0 = 0;
1597 isoc_req_tok_0 = 1;
1598 free_tokens = 4;
1599 probe_tok_0 = 1;
1600 rsp_tok_0 = 1;
1601 preq_tok_0 = 1;
1602 req_tok_0 = 1;
1603 } else if ((sockets == 4) && (sockets_populated == 4)) {
1604 isoc_rsp_tok_1 = 0;
1605 isoc_preq_tok_1 = 0;
1606 isoc_req_tok_1 = 1;
1607 probe_tok_1 = 1;
1608 rsp_tok_1 = 1;
1609 preq_tok_1 = 1;
1610 req_tok_1 = 1;
1611 isoc_rsp_tok_0 = 0;
1612 isoc_preq_tok_0 = 0;
1613 isoc_req_tok_0 = 1;
1614 free_tokens = 0;
1615 probe_tok_0 = 1;
1616 rsp_tok_0 = 1;
1617 preq_tok_0 = 1;
1618 req_tok_0 = 1;
1619 }
1620 } else if (iolink && ganged) {
1621 if (!dual_node) {
1622 isoc_rsp_tok_1 = 0;
1623 isoc_preq_tok_1 = 0;
1624 isoc_req_tok_1 = 0;
1625 probe_tok_1 = 0;
1626 rsp_tok_1 = 0;
1627 preq_tok_1 = 0;
1628 req_tok_1 = 0;
1629 isoc_rsp_tok_0 = 0;
1630 isoc_preq_tok_0 = 0;
1631 isoc_req_tok_0 = 1;
1632 free_tokens = 3;
1633 probe_tok_0 = 0;
1634 rsp_tok_0 = 2;
1635 preq_tok_0 = 2;
1636 req_tok_0 = 2;
1637 } else if ((sockets == 1)
1638 || (sockets == 2)
1639 || ((sockets == 4) && (sockets_populated == 2))) {
1640 isoc_rsp_tok_1 = 0;
1641 isoc_preq_tok_1 = 0;
1642 isoc_req_tok_1 = 0;
1643 probe_tok_1 = 0;
1644 rsp_tok_1 = 0;
1645 preq_tok_1 = 0;
1646 req_tok_1 = 0;
1647 isoc_rsp_tok_0 = 0;
1648 isoc_preq_tok_0 = 0;
1649 isoc_req_tok_0 = 1;
1650 free_tokens = 0;
1651 probe_tok_0 = 0;
1652 rsp_tok_0 = 2;
1653 preq_tok_0 = 2;
1654 req_tok_0 = 2;
1655 } else if ((sockets == 4) && (sockets_populated == 4)) {
1656 isoc_rsp_tok_1 = 0;
1657 isoc_preq_tok_1 = 0;
1658 isoc_req_tok_1 = 0;
1659 probe_tok_1 = 0;
1660 rsp_tok_1 = 0;
1661 preq_tok_1 = 0;
1662 req_tok_1 = 0;
1663 isoc_rsp_tok_0 = 0;
1664 isoc_preq_tok_0 = 0;
1665 isoc_req_tok_0 = 2;
1666 free_tokens = 0;
1667 probe_tok_0 = 2;
1668 rsp_tok_0 = 2;
1669 preq_tok_0 = 2;
1670 req_tok_0 = 2;
1671 }
1672 }
1673
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001674 dword = pci_read_config32(NODE_PCI(node, 3), (link_real << 2) + 0x148);
Timothy Pearson71b8f012015-08-07 23:59:17 -05001675 dword &= ~(0x3 << 30); /* FreeTok[3:2] = free_tokens[3:2] */
1676 dword |= (((free_tokens >> 2) & 0x3) << 30);
1677 dword &= ~(0x1 << 28); /* IsocRspTok1 = isoc_rsp_tok_1 */
1678 dword |= (((isoc_rsp_tok_1) & 0x1) << 28);
1679 dword &= ~(0x1 << 26); /* IsocPreqTok1 = isoc_preq_tok_1 */
1680 dword |= (((isoc_preq_tok_1) & 0x1) << 26);
1681 dword &= ~(0x1 << 24); /* IsocReqTok1 = isoc_req_tok_1 */
1682 dword |= (((isoc_req_tok_1) & 0x1) << 24);
1683 dword &= ~(0x3 << 22); /* ProbeTok1 = probe_tok_1 */
1684 dword |= (((probe_tok_1) & 0x3) << 22);
1685 dword &= ~(0x3 << 20); /* RspTok1 = rsp_tok_1 */
1686 dword |= (((rsp_tok_1) & 0x3) << 20);
1687 dword &= ~(0x3 << 18); /* PReqTok1 = preq_tok_1 */
1688 dword |= (((preq_tok_1) & 0x3) << 18);
1689 dword &= ~(0x3 << 16); /* ReqTok1 = req_tok_1 */
1690 dword |= (((req_tok_1) & 0x3) << 16);
1691 dword &= ~(0x3 << 14); /* FreeTok[1:0] = free_tokens[1:0] */
1692 dword |= (((free_tokens) & 0x3) << 14);
1693 dword &= ~(0x3 << 12); /* IsocRspTok0 = isoc_rsp_tok_0 */
1694 dword |= (((isoc_rsp_tok_0) & 0x3) << 12);
1695 dword &= ~(0x3 << 10); /* IsocPreqTok0 = isoc_preq_tok_0 */
1696 dword |= (((isoc_preq_tok_0) & 0x3) << 10);
1697 dword &= ~(0x3 << 8); /* IsocReqTok0 = isoc_req_tok_0 */
1698 dword |= (((isoc_req_tok_0) & 0x3) << 8);
1699 dword &= ~(0x3 << 6); /* ProbeTok0 = probe_tok_0 */
1700 dword |= (((probe_tok_0) & 0x3) << 6);
1701 dword &= ~(0x3 << 4); /* RspTok0 = rsp_tok_0 */
1702 dword |= (((rsp_tok_0) & 0x3) << 4);
1703 dword &= ~(0x3 << 2); /* PReqTok0 = preq_tok_0 */
1704 dword |= (((preq_tok_0) & 0x3) << 2);
1705 dword &= ~(0x3 << 0); /* ReqTok0 = req_tok_0 */
1706 dword |= (((req_tok_0) & 0x3) << 0);
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001707 pci_write_config32(NODE_PCI(node, 3), (link_real << 2) + 0x148, dword);
Timothy Pearson71b8f012015-08-07 23:59:17 -05001708 }
1709 }
Timothy Pearsonbaa1acd2015-08-08 22:14:59 -05001710
1711 /* Set up the SRI to XCS Token Count */
1712 uint8_t free_tok;
1713 uint8_t up_rsp_tok;
1714
1715 /* Set defaults */
1716 free_tok = 0xa;
1717 up_rsp_tok = 0x3;
1718
1719 if (!dual_node) {
1720 free_tok = 0xa;
1721 up_rsp_tok = 0x3;
1722 } else {
1723 if ((sockets == 1)
1724 || ((sockets == 2) && (sockets_populated == 1))) {
1725 if (probe_filter_enabled) {
1726 free_tok = 0x9;
1727 up_rsp_tok = 0x3;
1728 } else {
1729 free_tok = 0xa;
1730 up_rsp_tok = 0x3;
1731 }
1732 } else if ((sockets == 2) && (sockets_populated == 2)) {
1733 free_tok = 0xb;
1734 up_rsp_tok = 0x1;
1735 } else if ((sockets == 4) && (sockets_populated == 2)) {
1736 free_tok = 0xa;
1737 up_rsp_tok = 0x3;
1738 } else if ((sockets == 4) && (sockets_populated == 4)) {
1739 free_tok = 0x9;
1740 up_rsp_tok = 0x1;
1741 }
1742 }
1743
1744 dword = pci_read_config32(NODE_PCI(node, 3), 0x140);
1745 dword &= ~(0xf << 20); /* FreeTok = free_tok */
1746 dword |= ((free_tok & 0xf) << 20);
1747 dword &= ~(0x3 << 8); /* UpRspTok = up_rsp_tok */
1748 dword |= ((up_rsp_tok & 0x3) << 8);
1749 pci_write_config32(NODE_PCI(node, 3), 0x140, dword);
Timothy Pearson965704a2015-08-07 19:04:49 -05001750 }
1751
Timothy Pearson50001b82015-08-11 17:47:48 -05001752 uint8_t link;
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001753 uint8_t link_real;
Timothy Pearson50001b82015-08-11 17:47:48 -05001754 uint8_t isochronous;
1755 uint8_t isochronous_link_present;
1756
1757 /* Set up isochronous buffers if needed */
1758 isochronous_link_present = 0;
1759 if (revision & AMD_FAM15_ALL) {
1760 for (link = 0; link < 4; link++) {
1761 if (AMD_CpuFindCapability(node, link, &offset)) {
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001762 link_real = (offset - 0x80) / 0x20;
1763 isochronous = (pci_read_config32(NODE_PCI(node, 0), (link_real * 0x20) + 0x84) >> 12) & 0x1;
Timothy Pearson50001b82015-08-11 17:47:48 -05001764
1765 if (isochronous)
1766 isochronous_link_present = 1;
1767 }
1768 }
1769 }
1770
1771 uint8_t free_tok;
1772 uint8_t up_rsp_cbc;
1773 uint8_t isoc_preq_cbc;
1774 uint8_t isoc_preq_tok;
1775 uint8_t xbar_to_sri_free_list_cbc;
1776 if (isochronous_link_present) {
1777 /* Adjust buffer counts */
1778 dword = pci_read_config32(NODE_PCI(node, 3), 0x70);
1779 isoc_preq_cbc = (dword >> 24) & 0x7;
1780 up_rsp_cbc = (dword >> 16) & 0x7;
1781 up_rsp_cbc--;
1782 isoc_preq_cbc++;
1783 dword &= ~(0x7 << 24); /* IsocPreqCBC = isoc_preq_cbc */
1784 dword |= ((isoc_preq_cbc & 0x7) << 24);
1785 dword &= ~(0x7 << 16); /* UpRspCBC = up_rsp_cbc */
1786 dword |= ((up_rsp_cbc & 0x7) << 16);
1787 pci_write_config32(NODE_PCI(node, 3), 0x70, dword);
1788
1789 dword = pci_read_config32(NODE_PCI(node, 3), 0x74);
1790 isoc_preq_cbc = (dword >> 24) & 0x7;
1791 isoc_preq_cbc++;
1792 dword &= ~(0x7 << 24); /* IsocPreqCBC = isoc_preq_cbc */
1793 dword |= (isoc_preq_cbc & 0x7) << 24;
1794 pci_write_config32(NODE_PCI(node, 3), 0x74, dword);
1795
1796 dword = pci_read_config32(NODE_PCI(node, 3), 0x7c);
1797 xbar_to_sri_free_list_cbc = dword & 0x1f;
1798 xbar_to_sri_free_list_cbc--;
1799 dword &= ~0x1f; /* Xbar2SriFreeListCBC = xbar_to_sri_free_list_cbc */
1800 dword |= xbar_to_sri_free_list_cbc & 0x1f;
1801 pci_write_config32(NODE_PCI(node, 3), 0x7c, dword);
1802
1803 dword = pci_read_config32(NODE_PCI(node, 3), 0x140);
1804 free_tok = (dword >> 20) & 0xf;
1805 isoc_preq_tok = (dword >> 14) & 0x3;
1806 free_tok--;
1807 isoc_preq_tok++;
1808 dword &= ~(0xf << 20); /* FreeTok = free_tok */
1809 dword |= ((free_tok & 0xf) << 20);
1810 dword &= ~(0x3 << 14); /* IsocPreqTok = isoc_preq_tok */
1811 dword |= ((isoc_preq_tok & 0x3) << 14);
1812 pci_write_config32(NODE_PCI(node, 3), 0x140, dword);
1813 }
1814
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001815 printk(BIOS_DEBUG, " done\n");
1816}
1817
1818#ifdef UNUSED_CODE
Timothy Pearson730a0432015-10-16 13:51:51 -05001819/* Clearing the MCA registers is apparently handled in the ramstage CPU Function 3 driver */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001820static void cpuInitializeMCA(void)
1821{
1822 /* Clears Machine Check Architecture (MCA) registers, which power on
1823 * containing unknown data, on currently running processor.
1824 * This routine should only be executed on initial power on (cold boot),
1825 * not across a warm reset because valid data is present at that time.
1826 */
1827
1828 msr_t msr;
1829 u32 reg;
1830 u8 i;
1831
1832 if (cpuid_edx(1) & 0x4080) { /* MCE and MCA (edx[7] and edx[14]) */
Elyes HAOUAS400ce552018-10-12 10:54:30 +02001833 msr = rdmsr(IA32_MCG_CAP);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001834 if (msr.lo & MCG_CTL_P) { /* MCG_CTL_P bit is set? */
1835 msr.lo &= 0xFF;
1836 msr.lo--;
1837 msr.lo <<= 2; /* multiply the count by 4 */
Elyes HAOUAS400ce552018-10-12 10:54:30 +02001838 reg = IA32_MC0_STATUS + msr.lo;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001839 msr.lo = msr.hi = 0;
1840 for (i = 0; i < 4; i++) {
1841 wrmsr(reg, msr);
1842 reg -= 4; /* Touch status regs for each bank */
1843 }
1844 }
1845 }
1846}
1847#endif
1848
1849/**
1850 * finalize_node_setup()
1851 *
1852 * Do any additional post HT init
1853 *
1854 */
Damien Zammit75a3d1f2016-11-28 00:29:10 +11001855void finalize_node_setup(struct sys_info *sysinfo)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001856{
1857 u8 i;
1858 u8 nodes = get_nodes();
Patrick Georgif3e85422010-10-26 15:11:45 +00001859 u32 reg;
Kyösti Mälkki239c3d32013-12-27 14:46:32 +02001860
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001861 /* read Node0 F0_0x64 bit [8:10] to find out SbLink # */
1862 reg = pci_read_config32(NODE_HT(0), 0x64);
1863 sysinfo->sblk = (reg >> 8) & 7;
1864 sysinfo->sbbusn = 0;
1865 sysinfo->nodes = nodes;
1866 sysinfo->sbdn = get_sbdn(sysinfo->sbbusn);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001867
1868 for (i = 0; i < nodes; i++) {
1869 cpuSetAMDPCI(i);
1870 }
1871
Julius Wernercd49cce2019-03-05 16:53:33 -08001872#if CONFIG(SET_FIDVID)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001873 // Prep each node for FID/VID setup.
1874 prep_fid_change();
1875#endif
1876
1877#if CONFIG_MAX_PHYSICAL_CPUS > 1
1878 /* Skip the BSP, start at node 1 */
1879 for (i = 1; i < nodes; i++) {
1880 setup_remote_node(i);
1881 start_node(i);
1882 }
1883#endif
1884}
1885
Julius Wernercd49cce2019-03-05 16:53:33 -08001886#if CONFIG(SET_FIDVID)
Damien Zammit75a3d1f2016-11-28 00:29:10 +11001887# include "fidvid.c"
1888#endif