blob: 0ecd040253ab5b169117f5a9ae437fc053b9403a [file] [log] [blame]
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
Timothy Pearson1c4508e2015-09-05 17:50:29 -05005 * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000015 */
16
Damien Zammit75a3d1f2016-11-28 00:29:10 +110017#include "init_cpus.h"
18
Martin Roth5f46af62017-06-24 13:24:26 -060019#if IS_ENABLED(CONFIG_HAVE_OPTION_TABLE)
Damien Zammit75a3d1f2016-11-28 00:29:10 +110020#include "option_table.h"
21#endif
22#include <pc80/mc146818rtc.h>
23
24#include <northbridge/amd/amdht/ht_wrapper.h>
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000025#include <northbridge/amd/amdht/AsPsDefs.h>
26#include <northbridge/amd/amdht/porting.h>
Damien Zammit75a3d1f2016-11-28 00:29:10 +110027#include <northbridge/amd/amdht/h3ncmn.h>
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000028
Timothy Pearson83abd812015-06-08 19:35:06 -050029#if IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB700)
30#include <southbridge/amd/sb700/sb700.h>
31#endif
32
33#if IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB800)
34#include <southbridge/amd/sb800/sb800.h>
35#endif
36
Kyösti Mälkkib98391c2017-07-13 13:14:16 +030037#include "cpu/amd/car/disable_cache_as_ram.c"
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000038
Martin Roth5f46af62017-06-24 13:24:26 -060039#if IS_ENABLED(CONFIG_PCI_IO_CFG_EXT)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000040static void set_EnableCf8ExtCfg(void)
41{
42 // set the NB_CFG[46]=1;
43 msr_t msr;
44 msr = rdmsr(NB_CFG_MSR);
45 // EnableCf8ExtCfg: We need that to access CONFIG_PCI_IO_CFG_EXT 4K range
46 msr.hi |= (1 << (46 - 32));
47 wrmsr(NB_CFG_MSR, msr);
48}
49#else
50static void set_EnableCf8ExtCfg(void) { }
51#endif
52
Timothy Pearson0122afb2015-07-30 14:07:15 -050053// #define DEBUG_HT_SETUP 1
54// #define FAM10_AP_NODE_SEQUENTIAL_START 1
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000055
Timothy Pearson730a0432015-10-16 13:51:51 -050056uint32_t get_boot_apic_id(uint8_t node, uint32_t core) {
57 uint32_t ap_apicid;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000058
Timothy Pearson730a0432015-10-16 13:51:51 -050059 uint32_t nb_cfg_54;
60 uint32_t siblings;
61 uint32_t cores_found;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000062
Timothy Pearson730a0432015-10-16 13:51:51 -050063 uint8_t fam15h = 0;
Timothy Pearson1c4508e2015-09-05 17:50:29 -050064 uint8_t rev_gte_d = 0;
65 uint8_t dual_node = 0;
66 uint32_t f3xe8;
Timothy Pearson730a0432015-10-16 13:51:51 -050067 uint32_t family;
68 uint32_t model;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000069
Timothy Pearson730a0432015-10-16 13:51:51 -050070 uint32_t ApicIdCoreIdSize;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000071
72 /* Assume that all node are same stepping, otherwise we can use use
73 nb_cfg_54 from bsp for all nodes */
74 nb_cfg_54 = read_nb_cfg_54();
Timothy Pearson1c4508e2015-09-05 17:50:29 -050075 f3xe8 = pci_read_config32(NODE_PCI(0, 3), 0xe8);
76
Timothy Pearson730a0432015-10-16 13:51:51 -050077 family = model = cpuid_eax(0x80000001);
78 model = ((model & 0xf0000) >> 12) | ((model & 0xf0) >> 4);
79 family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);
80
81 if (family >= 0x6f) {
82 /* Family 15h or later */
83 fam15h = 1;
84 nb_cfg_54 = 1;
85 }
86
87 if ((model >= 0x8) || fam15h)
Timothy Pearson1c4508e2015-09-05 17:50:29 -050088 /* Revision D or later */
89 rev_gte_d = 1;
90
91 if (rev_gte_d)
92 /* Check for dual node capability */
93 if (f3xe8 & 0x20000000)
94 dual_node = 1;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000095
96 ApicIdCoreIdSize = (cpuid_ecx(0x80000008) >> 12 & 0xf);
97 if (ApicIdCoreIdSize) {
98 siblings = ((1 << ApicIdCoreIdSize) - 1);
99 } else {
100 siblings = 3; //quad core
101 }
102
Timothy Pearson730a0432015-10-16 13:51:51 -0500103 cores_found = get_core_num_in_bsp(node);
104 if (siblings > cores_found)
105 siblings = cores_found;
106
107 if (dual_node) {
108 ap_apicid = 0;
109 if (fam15h) {
110 ap_apicid |= ((node >> 1) & 0x3) << 5; /* Node ID */
111 ap_apicid |= ((node & 0x1) * (siblings + 1)) + core; /* Core ID */
112 } else {
113 if (nb_cfg_54) {
114 ap_apicid |= ((node >> 1) & 0x3) << 4; /* Node ID */
115 ap_apicid |= ((node & 0x1) * (siblings + 1)) + core; /* Core ID */
116 } else {
117 ap_apicid |= node & 0x3; /* Node ID */
118 ap_apicid |= (((node & 0x1) * (siblings + 1)) + core) << 4; /* Core ID */
119 }
120 }
121 } else {
122 if (fam15h) {
Timothy Pearson71f86412015-11-24 14:11:53 -0600123 ap_apicid = 0;
124 ap_apicid |= (node & 0x7) << 4; /* Node ID */
125 ap_apicid |= core & 0xf; /* Core ID */
Timothy Pearson730a0432015-10-16 13:51:51 -0500126 } else {
127 ap_apicid = node * (nb_cfg_54 ? (siblings + 1) : 1) +
128 core * (nb_cfg_54 ? 1 : 64);
129 }
130 }
131
Timothy Pearson71f86412015-11-24 14:11:53 -0600132 printk(BIOS_DEBUG, "%s: using %d as APIC ID for node %d, core %d\n", __func__, ap_apicid, node, core);
133
Timothy Pearson730a0432015-10-16 13:51:51 -0500134 return ap_apicid;
135}
136
137//core_range = 0 : all cores
138//core range = 1 : core 0 only
139//core range = 2 : cores other than core0
140
Timothy Pearson0122afb2015-07-30 14:07:15 -0500141static void for_each_ap(uint32_t bsp_apicid, uint32_t core_range, int8_t node,
142 process_ap_t process_ap, void *gp)
Timothy Pearson730a0432015-10-16 13:51:51 -0500143{
144 // here assume the OS don't change our apicid
145 u32 ap_apicid;
146
147 u32 nodes;
148 u32 disable_siblings;
149 u32 cores_found;
150 int i, j;
151
152 /* get_nodes define in ht_wrapper.c */
153 nodes = get_nodes();
154
Martin Roth5f46af62017-06-24 13:24:26 -0600155 if (!IS_ENABLED(CONFIG_LOGICAL_CPUS) ||
Timothy Pearson730a0432015-10-16 13:51:51 -0500156 read_option(multi_core, 0) != 0) { // 0 means multi core
157 disable_siblings = 1;
158 } else {
159 disable_siblings = 0;
160 }
161
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000162 for (i = 0; i < nodes; i++) {
Timothy Pearson0122afb2015-07-30 14:07:15 -0500163 if ((node >= 0) && (i != node))
164 continue;
165
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000166 cores_found = get_core_num_in_bsp(i);
167
168 u32 jstart, jend;
169
170 if (core_range == 2) {
171 jstart = 1;
172 } else {
173 jstart = 0;
174 }
175
176 if (disable_siblings || (core_range == 1)) {
177 jend = 0;
178 } else {
179 jend = cores_found;
180 }
181
182 for (j = jstart; j <= jend; j++) {
Timothy Pearson730a0432015-10-16 13:51:51 -0500183 ap_apicid = get_boot_apic_id(i, j);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000184
Martin Roth5f46af62017-06-24 13:24:26 -0600185#if IS_ENABLED(CONFIG_ENABLE_APIC_EXT_ID) && (CONFIG_APIC_ID_OFFSET > 0)
186#if !IS_ENABLED(CONFIG_LIFT_BSP_APIC_ID)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000187 if ((i != 0) || (j != 0)) /* except bsp */
188#endif
189 ap_apicid += CONFIG_APIC_ID_OFFSET;
190#endif
191
192 if (ap_apicid == bsp_apicid)
193 continue;
194
195 process_ap(ap_apicid, gp);
196
197 }
198 }
199}
200
201static inline int lapic_remote_read(int apicid, int reg, u32 *pvalue)
202{
203 int timeout;
204 u32 status;
205 int result;
206 lapic_wait_icr_idle();
207 lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
208 lapic_write(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4));
209
210/* Extra busy check compared to lapic.h */
211 timeout = 0;
212 do {
213 status = lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY;
214 } while (status == LAPIC_ICR_BUSY && timeout++ < 1000);
215
216 timeout = 0;
217 do {
218 status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK;
219 } while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000);
220
221 result = -1;
222
223 if (status == LAPIC_ICR_RR_VALID) {
224 *pvalue = lapic_read(LAPIC_RRR);
225 result = 0;
226 }
227 return result;
228}
229
Martin Roth5f46af62017-06-24 13:24:26 -0600230#if IS_ENABLED(CONFIG_SET_FIDVID)
Xavi Drudis Ferran6bdc83b2011-02-28 03:56:52 +0000231static void init_fidvid_ap(u32 apicid, u32 nodeid, u32 coreid);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000232#endif
233
Stefan Reinauer6a001132017-07-13 02:20:27 +0200234static inline __attribute__((always_inline))
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000235void print_apicid_nodeid_coreid(u32 apicid, struct node_core_id id,
236 const char *str)
237{
238 printk(BIOS_DEBUG,
239 "%s --- { APICID = %02x NODEID = %02x COREID = %02x} ---\n", str,
240 apicid, id.nodeid, id.coreid);
241}
242
Timothy Pearson730a0432015-10-16 13:51:51 -0500243uint32_t wait_cpu_state(uint32_t apicid, uint32_t state, uint32_t state2)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000244{
245 u32 readback = 0;
246 u32 timeout = 1;
247 int loop = 4000000;
248 while (--loop > 0) {
249 if (lapic_remote_read(apicid, LAPIC_MSG_REG, &readback) != 0)
250 continue;
Timothy Pearson730a0432015-10-16 13:51:51 -0500251 if ((readback & 0x3f) == state || (readback & 0x3f) == state2 || (readback & 0x3f) == F10_APSTATE_RESET) {
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000252 timeout = 0;
Elyes HAOUASd82be922016-07-28 18:58:27 +0200253 break; //target CPU is in stage started
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000254 }
255 }
256 if (timeout) {
257 if (readback) {
258 timeout = readback;
259 }
260 }
261
262 return timeout;
263}
264
265static void wait_ap_started(u32 ap_apicid, void *gp)
266{
267 u32 timeout;
Timothy Pearson730a0432015-10-16 13:51:51 -0500268 timeout = wait_cpu_state(ap_apicid, F10_APSTATE_STARTED, F10_APSTATE_ASLEEP);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000269 printk(BIOS_DEBUG, "* AP %02x", ap_apicid);
270 if (timeout) {
271 printk(BIOS_DEBUG, " timed out:%08x\n", timeout);
272 } else {
273 printk(BIOS_DEBUG, "started\n");
274 }
275}
276
277void wait_all_other_cores_started(u32 bsp_apicid)
278{
279 // all aps other than core0
280 printk(BIOS_DEBUG, "started ap apicid: ");
Timothy Pearson0122afb2015-07-30 14:07:15 -0500281 for_each_ap(bsp_apicid, 2, -1, wait_ap_started, (void *)0);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000282 printk(BIOS_DEBUG, "\n");
283}
284
285void allow_all_aps_stop(u32 bsp_apicid)
286{
287 /* Called by the BSP to indicate AP can stop */
288
289 /* FIXME Do APs use this? */
290
291 // allow aps to stop use 6 bits for state
292 lapic_write(LAPIC_MSG_REG, (bsp_apicid << 24) | F10_APSTATE_STOPPED);
293}
294
Timothy Pearsoncb1dec52015-11-24 14:12:02 -0600295static void wait_ap_stopped(u32 ap_apicid, void *gp)
296{
297 u32 timeout;
298 timeout = wait_cpu_state(ap_apicid, F10_APSTATE_ASLEEP, F10_APSTATE_ASLEEP);
299 printk(BIOS_DEBUG, "* AP %02x", ap_apicid);
300 if (timeout) {
301 printk(BIOS_DEBUG, " timed out:%08x\n", timeout);
302 } else {
303 printk(BIOS_DEBUG, "stopped\n");
304 }
305}
306
307void wait_all_other_cores_stopped(u32 bsp_apicid)
308{
309 // all aps other than core0
310 printk(BIOS_DEBUG, "stopped ap apicid: ");
311 for_each_ap(bsp_apicid, 2, -1, wait_ap_stopped, (void *)0);
312 printk(BIOS_DEBUG, "\n");
313}
314
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000315static void enable_apic_ext_id(u32 node)
316{
317 u32 val;
318
319 val = pci_read_config32(NODE_HT(node), 0x68);
320 val |= (HTTC_APIC_EXT_SPUR | HTTC_APIC_EXT_ID | HTTC_APIC_EXT_BRD_CST);
321 pci_write_config32(NODE_HT(node), 0x68, val);
322}
323
Timothy Pearson730a0432015-10-16 13:51:51 -0500324static void STOP_CAR_AND_CPU(uint8_t skip_sharedc_config, uint32_t apicid)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000325{
326 msr_t msr;
Timothy Pearson730a0432015-10-16 13:51:51 -0500327 uint32_t family;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000328
Timothy Pearson730a0432015-10-16 13:51:51 -0500329 family = amd_fam1x_cpu_family(); // inline
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000330
Timothy Pearson730a0432015-10-16 13:51:51 -0500331 if (family < 0x6f) {
332 /* Family 10h or earlier */
333
334 /* Disable L2 IC to L3 connection (Only for CAR) */
335 msr = rdmsr(BU_CFG2);
336 msr.lo &= ~(1 << ClLinesToNbDis);
337 wrmsr(BU_CFG2, msr);
Timothy Pearson38508a02015-06-25 15:07:34 -0500338 } else {
339 /* Family 15h or later
340 * DRAM setup is delayed on Fam15 in order to prevent
341 * any DRAM access before ECC check bits are initialized.
342 * Each core also needs to have its initial DRAM map initialized
343 * before it is put to sleep, otherwise it will fail to wake
344 * in ramstage. To meet both of these goals, delay DRAM map
345 * setup until the last possible moment, where speculative
346 * memory access is highly unlikely before core halt...
347 */
348 if (!skip_sharedc_config) {
349 /* Enable memory access for first MBs using top_mem */
350 msr.hi = 0;
351 msr.lo = (CONFIG_RAMTOP + TOP_MEM_MASK) & (~TOP_MEM_MASK);
352 wrmsr(TOP_MEM, msr);
353 }
Timothy Pearson730a0432015-10-16 13:51:51 -0500354 }
355
Kyösti Mälkkib98391c2017-07-13 13:14:16 +0300356 disable_cache_as_ram_real(skip_sharedc_config); // inline
Timothy Pearson730a0432015-10-16 13:51:51 -0500357
358 /* Mark the core as sleeping */
359 lapic_write(LAPIC_MSG_REG, (apicid << 24) | F10_APSTATE_ASLEEP);
360
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000361 /* stop all cores except node0/core0 the bsp .... */
362 stop_this_cpu();
363}
364
Damien Zammit75a3d1f2016-11-28 00:29:10 +1100365u32 init_cpus(u32 cpu_init_detectedx, struct sys_info *sysinfo)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000366{
Timothy Pearson0f1553b2015-08-02 21:06:39 -0500367 uint32_t bsp_apicid = 0;
368 uint32_t apicid;
369 uint32_t dword;
Timothy Pearson730a0432015-10-16 13:51:51 -0500370 uint8_t set_mtrrs;
Timothy Pearson0f1553b2015-08-02 21:06:39 -0500371 uint8_t node_count;
Timothy Pearson0df70462015-11-24 14:11:58 -0600372 uint8_t fam15_bsp_core1_apicid;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000373 struct node_core_id id;
374
Timothy Pearsonfb39f822015-06-02 20:25:03 -0500375 /* Please refer to the calculations and explaination in cache_as_ram.inc before modifying these values */
Timothy Pearsonb5e46552015-06-02 13:47:36 -0500376 uint32_t max_ap_stack_region_size = CONFIG_MAX_CPUS * CONFIG_DCACHE_AP_STACK_SIZE;
Timothy Pearsonfb39f822015-06-02 20:25:03 -0500377 uint32_t max_bsp_stack_region_size = CONFIG_DCACHE_BSP_STACK_SIZE + CONFIG_DCACHE_BSP_STACK_SLUSH;
378 uint32_t bsp_stack_region_upper_boundary = CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE;
379 uint32_t bsp_stack_region_lower_boundary = bsp_stack_region_upper_boundary - max_bsp_stack_region_size;
Timothy Pearsonb5e46552015-06-02 13:47:36 -0500380 void * lower_stack_region_boundary = (void*)(bsp_stack_region_lower_boundary - max_ap_stack_region_size);
381 if (((void*)(sysinfo + 1)) > lower_stack_region_boundary)
382 printk(BIOS_WARNING,
383 "sysinfo extends into stack region (sysinfo range: [%p,%p] lower stack region boundary: %p)\n",
384 sysinfo, sysinfo + 1, lower_stack_region_boundary);
385
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000386 /*
387 * already set early mtrr in cache_as_ram.inc
388 */
389
390 /* that is from initial apicid, we need nodeid and coreid
391 later */
392 id = get_node_core_id_x();
393
394 /* NB_CFG MSR is shared between cores, so we need make sure
395 core0 is done at first --- use wait_all_core0_started */
396 if (id.coreid == 0) {
Timothy Pearson0122afb2015-07-30 14:07:15 -0500397 /* Set InitApicIdCpuIdLo / EnableCf8ExtCfg on core0 only */
398 if (!is_fam15h())
399 set_apicid_cpuid_lo();
400 set_EnableCf8ExtCfg();
Martin Roth5f46af62017-06-24 13:24:26 -0600401#if IS_ENABLED(CONFIG_ENABLE_APIC_EXT_ID)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000402 enable_apic_ext_id(id.nodeid);
403#endif
404 }
405
406 enable_lapic();
407
Martin Roth5f46af62017-06-24 13:24:26 -0600408#if IS_ENABLED(CONFIG_ENABLE_APIC_EXT_ID) && (CONFIG_APIC_ID_OFFSET > 0)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000409 u32 initial_apicid = get_initial_apicid();
410
Martin Roth5f46af62017-06-24 13:24:26 -0600411#if !IS_ENABLED(CONFIG_LIFT_BSP_APIC_ID)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000412 if (initial_apicid != 0) // other than bsp
413#endif
414 {
Elyes HAOUASd6e96862016-08-21 10:12:15 +0200415 /* use initial APIC id to lift it */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000416 u32 dword = lapic_read(LAPIC_ID);
417 dword &= ~(0xff << 24);
418 dword |=
419 (((initial_apicid + CONFIG_APIC_ID_OFFSET) & 0xff) << 24);
420
421 lapic_write(LAPIC_ID, dword);
422 }
Martin Roth5f46af62017-06-24 13:24:26 -0600423#if IS_ENABLED(CONFIG_LIFT_BSP_APIC_ID)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000424 bsp_apicid += CONFIG_APIC_ID_OFFSET;
425#endif
426
427#endif
428
429 /* get the apicid, it may be lifted already */
430 apicid = lapicid();
431
432 // show our apicid, nodeid, and coreid
433 if (id.coreid == 0) {
434 if (id.nodeid != 0) //all core0 except bsp
435 print_apicid_nodeid_coreid(apicid, id, " core0: ");
436 } else { //all other cores
437 print_apicid_nodeid_coreid(apicid, id, " corex: ");
438 }
439
440 if (cpu_init_detectedx) {
441 print_apicid_nodeid_coreid(apicid, id,
442 "\n\n\nINIT detected from ");
443 printk(BIOS_DEBUG, "\nIssuing SOFT_RESET...\n");
444 soft_reset();
445 }
446
447 if (id.coreid == 0) {
448 if (!(warm_reset_detect(id.nodeid))) //FIXME: INIT is checked above but check for more resets?
449 distinguish_cpu_resets(id.nodeid); // Also indicates we are started
450 }
451 // Mark the core as started.
452 lapic_write(LAPIC_MSG_REG, (apicid << 24) | F10_APSTATE_STARTED);
Timothy Pearson0122afb2015-07-30 14:07:15 -0500453 printk(BIOS_DEBUG, "CPU APICID %02x start flag set\n", apicid);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000454
455 if (apicid != bsp_apicid) {
456 /* Setup each AP's cores MSRs.
457 * This happens after HTinit.
458 * The BSP runs this code in it's own path.
459 */
460 update_microcode(cpuid_eax(1));
Kyösti Mälkkif0a13ce2013-12-08 07:20:48 +0200461
Timothy Pearson730a0432015-10-16 13:51:51 -0500462 cpuSetAMDMSR(id.nodeid);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000463
Timothy Pearson0f1553b2015-08-02 21:06:39 -0500464 /* Set up HyperTransport probe filter support */
465 if (is_gt_rev_d()) {
466 dword = pci_read_config32(NODE_PCI(id.nodeid, 0), 0x60);
467 node_count = ((dword >> 4) & 0x7) + 1;
468
469 if (node_count > 1) {
470 msr_t msr = rdmsr(BU_CFG2_MSR);
471 msr.hi |= 1 << (42 - 32);
472 wrmsr(BU_CFG2_MSR, msr);
473 }
474 }
475
Martin Roth5f46af62017-06-24 13:24:26 -0600476#if IS_ENABLED(CONFIG_SET_FIDVID)
477#if IS_ENABLED(CONFIG_LOGICAL_CPUS) && IS_ENABLED(CONFIG_SET_FIDVID_CORE0_ONLY)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000478 // Run on all AP for proper FID/VID setup.
479 if (id.coreid == 0) // only need set fid for core0
480#endif
481 {
482 // check warm(bios) reset to call stage2 otherwise do stage1
483 if (warm_reset_detect(id.nodeid)) {
484 printk(BIOS_DEBUG,
485 "init_fidvid_stage2 apicid: %02x\n",
486 apicid);
487 init_fidvid_stage2(apicid, id.nodeid);
488 } else {
489 printk(BIOS_DEBUG,
490 "init_fidvid_ap(stage1) apicid: %02x\n",
491 apicid);
Xavi Drudis Ferran6bdc83b2011-02-28 03:56:52 +0000492 init_fidvid_ap(apicid, id.nodeid, id.coreid);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000493 }
494 }
495#endif
496
Timothy Pearson730a0432015-10-16 13:51:51 -0500497 if (is_fam15h()) {
498 /* core 1 on node 0 is special; to avoid corrupting the
499 * BSP do not alter MTRRs on that core */
Timothy Pearson0df70462015-11-24 14:11:58 -0600500 if (IS_ENABLED(CONFIG_ENABLE_APIC_EXT_ID) && (CONFIG_APIC_ID_OFFSET > 0))
501 fam15_bsp_core1_apicid = CONFIG_APIC_ID_OFFSET + 1;
502 else
503 fam15_bsp_core1_apicid = 1;
504
505 if (apicid == fam15_bsp_core1_apicid)
Timothy Pearson730a0432015-10-16 13:51:51 -0500506 set_mtrrs = 0;
507 else
508 set_mtrrs = !!(apicid & 0x1);
509 } else {
510 set_mtrrs = 1;
511 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000512
Timothy Pearson730a0432015-10-16 13:51:51 -0500513 /* AP is ready, configure MTRRs and go to sleep */
514 if (set_mtrrs)
Kyösti Mälkki65cc5262016-06-19 20:38:41 +0300515 set_var_mtrr(0, 0x00000000, CACHE_TMP_RAMTOP, MTRR_TYPE_WRBACK);
Timothy Pearson730a0432015-10-16 13:51:51 -0500516
517 printk(BIOS_DEBUG, "Disabling CAR on AP %02x\n", apicid);
518 if (is_fam15h()) {
519 /* Only modify the MSRs on the odd cores (the last cores to finish booting) */
520 STOP_CAR_AND_CPU(!set_mtrrs, apicid);
521 } else {
522 /* Modify MSRs on all cores */
523 STOP_CAR_AND_CPU(0, apicid);
524 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000525
526 printk(BIOS_DEBUG,
527 "\nAP %02x should be halted but you are reading this....\n",
528 apicid);
529 }
530
531 return bsp_apicid;
532}
533
534static u32 is_core0_started(u32 nodeid)
535{
536 u32 htic;
Antonello Dettoria422ffc2016-09-03 10:43:20 +0200537 pci_devfn_t device;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000538 device = NODE_PCI(nodeid, 0);
539 htic = pci_read_config32(device, HT_INIT_CONTROL);
540 htic &= HTIC_ColdR_Detect;
541 return htic;
542}
543
544void wait_all_core0_started(void)
545{
546 /* When core0 is started, it will distingush_cpu_resets
547 * So wait for that to finish */
548 u32 i;
549 u32 nodes = get_nodes();
550
551 printk(BIOS_DEBUG, "core0 started: ");
552 for (i = 1; i < nodes; i++) { // skip bsp, because it is running on bsp
553 while (!is_core0_started(i)) {
554 }
555 printk(BIOS_DEBUG, " %02x", i);
556 }
557 printk(BIOS_DEBUG, "\n");
558}
559
560#if CONFIG_MAX_PHYSICAL_CPUS > 1
561/**
562 * void start_node(u32 node)
563 *
564 * start the core0 in node, so it can generate HT packet to feature code.
565 *
566 * This function starts the AP nodes core0s. wait_all_core0_started() in
567 * romstage.c waits for all the AP to be finished before continuing
568 * system init.
569 */
570static void start_node(u8 node)
571{
572 u32 val;
573
574 /* Enable routing table */
575 printk(BIOS_DEBUG, "Start node %02x", node);
576
Martin Roth5f46af62017-06-24 13:24:26 -0600577#if IS_ENABLED(CONFIG_NORTHBRIDGE_AMD_AMDFAM10)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000578 /* For FAM10 support, we need to set Dram base/limit for the new node */
579 pci_write_config32(NODE_MP(node), 0x44, 0);
580 pci_write_config32(NODE_MP(node), 0x40, 3);
581#endif
582
583 /* Allow APs to make requests (ROM fetch) */
584 val = pci_read_config32(NODE_HT(node), 0x6c);
585 val &= ~(1 << 1);
586 pci_write_config32(NODE_HT(node), 0x6c, val);
587
588 printk(BIOS_DEBUG, " done.\n");
589}
590
591/**
592 * static void setup_remote_node(u32 node)
593 *
Martin Roth4c3ab732013-07-08 16:23:54 -0600594 * Copy the BSP Address Map to each AP.
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000595 */
596static void setup_remote_node(u8 node)
597{
598 /* There registers can be used with F1x114_x Address Map at the
599 same time, So must set them even 32 node */
600 static const u16 pci_reg[] = {
601 /* DRAM Base/Limits Registers */
602 0x44, 0x4c, 0x54, 0x5c, 0x64, 0x6c, 0x74, 0x7c,
603 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78,
604 0x144, 0x14c, 0x154, 0x15c, 0x164, 0x16c, 0x174, 0x17c,
605 0x140, 0x148, 0x150, 0x158, 0x160, 0x168, 0x170, 0x178,
606 /* MMIO Base/Limits Registers */
607 0x84, 0x8c, 0x94, 0x9c, 0xa4, 0xac, 0xb4, 0xbc,
608 0x80, 0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8,
609 /* IO Base/Limits Registers */
610 0xc4, 0xcc, 0xd4, 0xdc,
611 0xc0, 0xc8, 0xd0, 0xd8,
612 /* Configuration Map Registers */
613 0xe0, 0xe4, 0xe8, 0xec,
614 };
615 u16 i;
616
617 printk(BIOS_DEBUG, "setup_remote_node: %02x", node);
618
619 /* copy the default resource map from node 0 */
620 for (i = 0; i < ARRAY_SIZE(pci_reg); i++) {
621 u32 value;
622 u16 reg;
623 reg = pci_reg[i];
624 value = pci_read_config32(NODE_MP(0), reg);
625 pci_write_config32(NODE_MP(node), reg, value);
626
627 }
628 printk(BIOS_DEBUG, " done\n");
629}
630#endif /* CONFIG_MAX_PHYSICAL_CPUS > 1 */
631
Timothy Pearson0122afb2015-07-30 14:07:15 -0500632//it is running on core0 of node0
Damien Zammit75a3d1f2016-11-28 00:29:10 +1100633void start_other_cores(uint32_t bsp_apicid)
Timothy Pearson0122afb2015-07-30 14:07:15 -0500634{
635 u32 nodes;
636 u32 nodeid;
637
638 // disable multi_core
639 if (read_option(multi_core, 0) != 0) {
640 printk(BIOS_DEBUG, "Skip additional core init\n");
641 return;
642 }
643
644 nodes = get_nodes();
645
646 for (nodeid = 0; nodeid < nodes; nodeid++) {
647 u32 cores = get_core_num_in_bsp(nodeid);
648 printk(BIOS_DEBUG, "init node: %02x cores: %02x pass 1\n", nodeid, cores);
649 if (cores > 0) {
650 real_start_other_core(nodeid, cores);
651#ifdef FAM10_AP_NODE_SEQUENTIAL_START
652 printk(BIOS_DEBUG, "waiting for core start on node %d...\n", nodeid);
653 for_each_ap(bsp_apicid, 2, nodeid, wait_ap_started, (void *)0);
654 printk(BIOS_DEBUG, "...started\n");
655#endif
656 }
657 }
658}
659
Timothy Pearson730a0432015-10-16 13:51:51 -0500660static void AMD_Errata281(u8 node, uint64_t revision, u32 platform)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000661{
662 /* Workaround for Transaction Scheduling Conflict in
663 * Northbridge Cross Bar. Implement XCS Token adjustment
664 * for ganged links. Also, perform fix up for the mixed
665 * revision case.
666 */
667
668 u32 reg, val;
669 u8 i;
670 u8 mixed = 0;
671 u8 nodes = get_nodes();
672
673 if (platform & AMD_PTYPE_SVR) {
674 /* For each node we need to check for a "broken" node */
675 if (!(revision & (AMD_DR_B0 | AMD_DR_B1))) {
676 for (i = 0; i < nodes; i++) {
677 if (mctGetLogicalCPUID(i) &
678 (AMD_DR_B0 | AMD_DR_B1)) {
679 mixed = 1;
680 break;
681 }
682 }
683 }
684
685 if ((revision & (AMD_DR_B0 | AMD_DR_B1)) || mixed) {
686
687 /* F0X68[22:21] DsNpReqLmt0 = 01b */
688 val = pci_read_config32(NODE_PCI(node, 0), 0x68);
689 val &= ~0x00600000;
690 val |= 0x00200000;
691 pci_write_config32(NODE_PCI(node, 0), 0x68, val);
692
693 /* F3X6C */
694 val = pci_read_config32(NODE_PCI(node, 3), 0x6C);
695 val &= ~0x700780F7;
696 val |= 0x00010094;
697 pci_write_config32(NODE_PCI(node, 3), 0x6C, val);
698
699 /* F3X7C */
700 val = pci_read_config32(NODE_PCI(node, 3), 0x7C);
701 val &= ~0x707FFF1F;
702 val |= 0x00144514;
703 pci_write_config32(NODE_PCI(node, 3), 0x7C, val);
704
705 /* F3X144[3:0] RspTok = 0001b */
706 val = pci_read_config32(NODE_PCI(node, 3), 0x144);
707 val &= ~0x0000000F;
708 val |= 0x00000001;
709 pci_write_config32(NODE_PCI(node, 3), 0x144, val);
710
711 for (i = 0; i < 3; i++) {
712 reg = 0x148 + (i * 4);
713 val = pci_read_config32(NODE_PCI(node, 3), reg);
714 val &= ~0x000000FF;
715 val |= 0x000000DB;
716 pci_write_config32(NODE_PCI(node, 3), reg, val);
717 }
718 }
719 }
720}
721
722static void AMD_Errata298(void)
723{
724 /* Workaround for L2 Eviction May Occur during operation to
725 * set Accessed or dirty bit.
726 */
727
728 msr_t msr;
729 u8 i;
730 u8 affectedRev = 0;
731 u8 nodes = get_nodes();
732
733 /* For each core we need to check for a "broken" node */
734 for (i = 0; i < nodes; i++) {
735 if (mctGetLogicalCPUID(i) & (AMD_DR_B0 | AMD_DR_B1 | AMD_DR_B2)) {
736 affectedRev = 1;
737 break;
738 }
739 }
740
741 if (affectedRev) {
742 msr = rdmsr(HWCR);
743 msr.lo |= 0x08; /* Set TlbCacheDis bit[3] */
744 wrmsr(HWCR, msr);
745
746 msr = rdmsr(BU_CFG);
747 msr.lo |= 0x02; /* Set TlbForceMemTypeUc bit[1] */
748 wrmsr(BU_CFG, msr);
749
750 msr = rdmsr(OSVW_ID_Length);
751 msr.lo |= 0x01; /* OS Visible Workaround - MSR */
752 wrmsr(OSVW_ID_Length, msr);
753
754 msr = rdmsr(OSVW_Status);
755 msr.lo |= 0x01; /* OS Visible Workaround - MSR */
756 wrmsr(OSVW_Status, msr);
757 }
758
759 if (!affectedRev && (mctGetLogicalCPUID(0xFF) & AMD_DR_B3)) {
760 msr = rdmsr(OSVW_ID_Length);
761 msr.lo |= 0x01; /* OS Visible Workaround - MSR */
762 wrmsr(OSVW_ID_Length, msr);
763
764 }
765}
766
767static u32 get_platform_type(void)
768{
769 u32 ret = 0;
770
771 switch (SYSTEM_TYPE) {
772 case 1:
773 ret |= AMD_PTYPE_DSK;
774 break;
775 case 2:
776 ret |= AMD_PTYPE_MOB;
777 break;
778 case 0:
779 ret |= AMD_PTYPE_SVR;
780 break;
781 default:
782 break;
783 }
784
785 /* FIXME: add UMA support. */
786
787 /* All Fam10 are multi core */
788 ret |= AMD_PTYPE_MC;
789
790 return ret;
791}
792
793static void AMD_SetupPSIVID_d(u32 platform_type, u8 node)
794{
795 u32 dword;
796 int i;
797 msr_t msr;
798
799 if (platform_type & (AMD_PTYPE_MOB | AMD_PTYPE_DSK)) {
800
801 /* The following code sets the PSIVID to the lowest support P state
802 * assuming that the VID for the lowest power state is below
803 * the VDD voltage regulator threshold. (This also assumes that there
804 * is a Pstate lower than P0)
805 */
806
807 for (i = 4; i >= 0; i--) {
808 msr = rdmsr(PS_REG_BASE + i);
809 /* Pstate valid? */
810 if (msr.hi & PS_EN_MASK) {
811 dword = pci_read_config32(NODE_PCI(i, 3), 0xA0);
812 dword &= ~0x7F;
813 dword |= (msr.lo >> 9) & 0x7F;
814 pci_write_config32(NODE_PCI(i, 3), 0xA0, dword);
815 break;
816 }
817 }
818 }
819}
820
821/**
822 * AMD_CpuFindCapability - Traverse PCI capability list to find host HT links.
823 * HT Phy operations are not valid on links that aren't present, so this
824 * prevents invalid accesses.
825 *
826 * Returns the offset of the link register.
827 */
828static BOOL AMD_CpuFindCapability(u8 node, u8 cap_count, u8 * offset)
829{
830 u32 reg;
831 u32 val;
832
833 /* get start of CPU HT Host Capabilities */
834 val = pci_read_config32(NODE_PCI(node, 0), 0x34);
835 val &= 0xFF; //reg offset of first link
836
837 cap_count++;
838
839 /* Traverse through the capabilities. */
840 do {
841 reg = pci_read_config32(NODE_PCI(node, 0), val);
842 /* Is the capability block a HyperTransport capability block? */
843 if ((reg & 0xFF) == 0x08) {
844 /* Is the HT capability block an HT Host Capability? */
845 if ((reg & 0xE0000000) == (1 << 29))
846 cap_count--;
847 }
848
849 if (cap_count)
850 val = (reg >> 8) & 0xFF; //update reg offset
851 } while (cap_count && val);
852
853 *offset = (u8) val;
854
855 /* If requested capability found val != 0 */
856 if (!cap_count)
857 return TRUE;
858 else
859 return FALSE;
860}
861
862/**
863 * AMD_checkLinkType - Compare desired link characteristics using a logical
864 * link type mask.
865 *
866 * Returns the link characteristic mask.
867 */
Timothy Pearsonf8549e82015-09-07 22:26:55 -0500868static u32 AMD_checkLinkType(u8 node, u8 regoff)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000869{
Timothy Pearson965704a2015-08-07 19:04:49 -0500870 uint32_t val;
871 uint32_t val2;
872 uint32_t linktype = 0;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000873
874 /* Check connect, init and coherency */
875 val = pci_read_config32(NODE_PCI(node, 0), regoff + 0x18);
876 val &= 0x1F;
877
878 if (val == 3)
879 linktype |= HTPHY_LINKTYPE_COHERENT;
880
881 if (val == 7)
882 linktype |= HTPHY_LINKTYPE_NONCOHERENT;
883
884 if (linktype) {
885 /* Check gen3 */
886 val = pci_read_config32(NODE_PCI(node, 0), regoff + 0x08);
Timothy Pearson965704a2015-08-07 19:04:49 -0500887 val = (val >> 8) & 0xf;
888 if (is_gt_rev_d()) {
889 val2 = pci_read_config32(NODE_PCI(node, 0), regoff + 0x1c);
890 val |= (val2 & 0x1) << 4;
891 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000892
Timothy Pearson965704a2015-08-07 19:04:49 -0500893 if (val > 6)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000894 linktype |= HTPHY_LINKTYPE_HT3;
895 else
896 linktype |= HTPHY_LINKTYPE_HT1;
897
898 /* Check ganged */
Timothy Pearsonf8549e82015-09-07 22:26:55 -0500899 val = pci_read_config32(NODE_PCI(node, 0), (((regoff - 0x80) / 0x20) << 2) + 0x170);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000900
901 if (val & 1)
902 linktype |= HTPHY_LINKTYPE_GANGED;
903 else
904 linktype |= HTPHY_LINKTYPE_UNGANGED;
905 }
Timothy Pearsone536a4d2015-08-02 21:31:17 -0500906
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000907 return linktype;
908}
909
910/**
911 * AMD_SetHtPhyRegister - Use the HT link's HT Phy portal registers to update
912 * a phy setting for that link.
913 */
914static void AMD_SetHtPhyRegister(u8 node, u8 link, u8 entry)
915{
916 u32 phyReg;
917 u32 phyBase;
918 u32 val;
919
920 /* Determine this link's portal */
921 if (link > 3)
922 link -= 4;
923
924 phyBase = ((u32) link << 3) | 0x180;
925
Timothy Pearson0122afb2015-07-30 14:07:15 -0500926 /* Determine if link is connected and abort if not */
927 if (!(pci_read_config32(NODE_PCI(node, 0), 0x98 + (link * 0x20)) & 0x1))
928 return;
929
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000930 /* Get the portal control register's initial value
931 * and update it to access the desired phy register
932 */
933 phyReg = pci_read_config32(NODE_PCI(node, 4), phyBase);
934
935 if (fam10_htphy_default[entry].htreg > 0x1FF) {
936 phyReg &= ~HTPHY_DIRECT_OFFSET_MASK;
937 phyReg |= HTPHY_DIRECT_MAP;
938 } else {
939 phyReg &= ~HTPHY_OFFSET_MASK;
940 }
941
942 /* Now get the current phy register data
943 * LinkPhyDone = 0, LinkPhyWrite = 0 is a read
944 */
945 phyReg |= fam10_htphy_default[entry].htreg;
946 pci_write_config32(NODE_PCI(node, 4), phyBase, phyReg);
947
948 do {
949 val = pci_read_config32(NODE_PCI(node, 4), phyBase);
950 } while (!(val & HTPHY_IS_COMPLETE_MASK));
951
952 /* Now we have the phy register data, apply the change */
953 val = pci_read_config32(NODE_PCI(node, 4), phyBase + 4);
954 val &= ~fam10_htphy_default[entry].mask;
955 val |= fam10_htphy_default[entry].data;
956 pci_write_config32(NODE_PCI(node, 4), phyBase + 4, val);
957
958 /* write it through the portal to the phy
959 * LinkPhyDone = 0, LinkPhyWrite = 1 is a write
960 */
961 phyReg |= HTPHY_WRITE_CMD;
962 pci_write_config32(NODE_PCI(node, 4), phyBase, phyReg);
963
964 do {
965 val = pci_read_config32(NODE_PCI(node, 4), phyBase);
966 } while (!(val & HTPHY_IS_COMPLETE_MASK));
967}
968
Timothy Pearson730a0432015-10-16 13:51:51 -0500969void cpuSetAMDMSR(uint8_t node_id)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000970{
971 /* This routine loads the CPU with default settings in fam10_msr_default
972 * table . It must be run after Cache-As-RAM has been enabled, and
973 * Hypertransport initialization has taken place. Also note
974 * that it is run on the current processor only, and only for the current
975 * processor core.
976 */
977 msr_t msr;
978 u8 i;
Timothy Pearson68130f52015-08-09 02:47:51 -0500979 uint8_t nvram;
Timothy Pearson730a0432015-10-16 13:51:51 -0500980 u32 platform;
981 uint64_t revision;
Timothy Pearson83abd812015-06-08 19:35:06 -0500982 uint8_t enable_c_states;
Timothy Pearson4e543d32015-11-24 14:12:07 -0600983 uint8_t enable_cpb;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000984
985 printk(BIOS_DEBUG, "cpuSetAMDMSR ");
986
987 revision = mctGetLogicalCPUID(0xFF);
988 platform = get_platform_type();
989
990 for (i = 0; i < ARRAY_SIZE(fam10_msr_default); i++) {
991 if ((fam10_msr_default[i].revision & revision) &&
992 (fam10_msr_default[i].platform & platform)) {
993 msr = rdmsr(fam10_msr_default[i].msr);
994 msr.hi &= ~fam10_msr_default[i].mask_hi;
995 msr.hi |= fam10_msr_default[i].data_hi;
996 msr.lo &= ~fam10_msr_default[i].mask_lo;
997 msr.lo |= fam10_msr_default[i].data_lo;
998 wrmsr(fam10_msr_default[i].msr, msr);
999 }
1000 }
1001 AMD_Errata298();
1002
Timothy Pearson730a0432015-10-16 13:51:51 -05001003 /* Revision C0 and above */
1004 if (revision & AMD_OR_C0) {
Timothy Pearson68130f52015-08-09 02:47:51 -05001005 uint8_t enable_experimental_memory_speed_boost;
1006
1007 /* Check to see if cache partitioning is allowed */
1008 enable_experimental_memory_speed_boost = 0;
1009 if (get_option(&nvram, "experimental_memory_speed_boost") == CB_SUCCESS)
1010 enable_experimental_memory_speed_boost = !!nvram;
1011
Timothy Pearson730a0432015-10-16 13:51:51 -05001012 uint32_t f3x1fc = pci_read_config32(NODE_PCI(node_id, 3), 0x1fc);
1013 msr = rdmsr(FP_CFG);
1014 msr.hi &= ~(0x7 << (42-32)); /* DiDtCfg4 */
1015 msr.hi |= (((f3x1fc >> 17) & 0x7) << (42-32));
1016 msr.hi &= ~(0x1 << (41-32)); /* DiDtCfg5 */
1017 msr.hi |= (((f3x1fc >> 22) & 0x1) << (41-32));
1018 msr.hi &= ~(0x1 << (40-32)); /* DiDtCfg3 */
1019 msr.hi |= (((f3x1fc >> 16) & 0x1) << (40-32));
1020 msr.hi &= ~(0x7 << (32-32)); /* DiDtCfg1 (1) */
1021 msr.hi |= (((f3x1fc >> 11) & 0x7) << (32-32));
1022 msr.lo &= ~(0x1f << 27); /* DiDtCfg1 (2) */
1023 msr.lo |= (((f3x1fc >> 6) & 0x1f) << 27);
1024 msr.lo &= ~(0x3 << 25); /* DiDtCfg2 */
1025 msr.lo |= (((f3x1fc >> 14) & 0x3) << 25);
1026 msr.lo &= ~(0x1f << 18); /* DiDtCfg0 */
1027 msr.lo |= (((f3x1fc >> 1) & 0x1f) << 18);
1028 msr.lo &= ~(0x1 << 16); /* DiDtMode */
1029 msr.lo |= ((f3x1fc & 0x1) << 16);
1030 wrmsr(FP_CFG, msr);
Timothy Pearson68130f52015-08-09 02:47:51 -05001031
1032 if (enable_experimental_memory_speed_boost) {
1033 msr = rdmsr(BU_CFG3);
1034 msr.lo |= (0x3 << 20); /* PfcStrideMul = 0x3 */
1035 wrmsr(BU_CFG3, msr);
1036 }
Timothy Pearson730a0432015-10-16 13:51:51 -05001037 }
1038
Timothy Pearson83abd812015-06-08 19:35:06 -05001039#if IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB700) || IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB800)
Timothy Pearson83abd812015-06-08 19:35:06 -05001040 if (revision & (AMD_DR_GT_D0 | AMD_FAM15_ALL)) {
1041 /* Set up message triggered C1E */
1042 msr = rdmsr(0xc0010055);
1043 msr.lo &= ~0xffff; /* IOMsgAddr = ACPI_PM_EVT_BLK */
1044 msr.lo |= ACPI_PM_EVT_BLK & 0xffff;
1045 msr.lo |= (0x1 << 29); /* BmStsClrOnHltEn = 1 */
1046 if (revision & AMD_DR_GT_D0) {
1047 msr.lo &= ~(0x1 << 28); /* C1eOnCmpHalt = 0 */
1048 msr.lo &= ~(0x1 << 27); /* SmiOnCmpHalt = 0 */
1049 }
1050 wrmsr(0xc0010055, msr);
1051
1052 msr = rdmsr(0xc0010015);
1053 msr.lo |= (0x1 << 12); /* HltXSpCycEn = 1 */
1054 wrmsr(0xc0010015, msr);
1055 }
1056
1057 if (revision & (AMD_DR_Ex | AMD_FAM15_ALL)) {
1058 enable_c_states = 0;
1059 if (IS_ENABLED(CONFIG_HAVE_ACPI_TABLES))
1060 if (get_option(&nvram, "cpu_c_states") == CB_SUCCESS)
1061 enable_c_states = !!nvram;
1062
1063 if (enable_c_states) {
1064 /* Set up the C-state base address */
1065 msr_t c_state_addr_msr;
1066 c_state_addr_msr = rdmsr(0xc0010073);
1067 c_state_addr_msr.lo = ACPI_CPU_P_LVL2; /* CstateAddr = ACPI_CPU_P_LVL2 */
1068 wrmsr(0xc0010073, c_state_addr_msr);
1069 }
1070 }
1071#else
1072 enable_c_states = 0;
1073#endif
1074
Timothy Pearson4e543d32015-11-24 14:12:07 -06001075 if (revision & AMD_FAM15_ALL) {
1076 enable_cpb = 1;
1077 if (get_option(&nvram, "cpu_core_boost") == CB_SUCCESS)
1078 enable_cpb = !!nvram;
1079
1080 if (!enable_cpb) {
1081 /* Disable Core Performance Boost */
1082 msr = rdmsr(0xc0010015);
1083 msr.lo |= (0x1 << 25); /* CpbDis = 1 */
1084 wrmsr(0xc0010015, msr);
1085 }
1086 }
1087
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001088 printk(BIOS_DEBUG, " done\n");
1089}
1090
1091static void cpuSetAMDPCI(u8 node)
1092{
1093 /* This routine loads the CPU with default settings in fam10_pci_default
1094 * table . It must be run after Cache-As-RAM has been enabled, and
1095 * Hypertransport initialization has taken place. Also note
1096 * that it is run for the first core on each node
1097 */
Timothy Pearson0122afb2015-07-30 14:07:15 -05001098 uint8_t i;
1099 uint8_t j;
Timothy Pearson730a0432015-10-16 13:51:51 -05001100 u32 platform;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001101 u32 val;
Timothy Pearson0122afb2015-07-30 14:07:15 -05001102 uint8_t offset;
Timothy Pearson83abd812015-06-08 19:35:06 -05001103 uint32_t dword;
Timothy Pearson730a0432015-10-16 13:51:51 -05001104 uint64_t revision;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001105
Timothy Pearson71b8f012015-08-07 23:59:17 -05001106 /* FIXME
1107 * This should be configurable
1108 */
1109 uint8_t sockets = 2;
1110 uint8_t sockets_populated = 2;
1111
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001112 printk(BIOS_DEBUG, "cpuSetAMDPCI %02d", node);
1113
1114 revision = mctGetLogicalCPUID(node);
1115 platform = get_platform_type();
1116
1117 AMD_SetupPSIVID_d(platform, node); /* Set PSIVID offset which is not table driven */
1118
1119 for (i = 0; i < ARRAY_SIZE(fam10_pci_default); i++) {
1120 if ((fam10_pci_default[i].revision & revision) &&
1121 (fam10_pci_default[i].platform & platform)) {
1122 val = pci_read_config32(NODE_PCI(node,
1123 fam10_pci_default[i].
1124 function),
1125 fam10_pci_default[i].offset);
1126 val &= ~fam10_pci_default[i].mask;
1127 val |= fam10_pci_default[i].data;
1128 pci_write_config32(NODE_PCI(node,
1129 fam10_pci_default[i].
1130 function),
1131 fam10_pci_default[i].offset, val);
1132 }
1133 }
1134
Timothy Pearson39495ba2015-11-24 14:11:47 -06001135 if (is_fam15h()) {
1136 if (CONFIG_CPU_SOCKET_TYPE == 0x14) {
1137 /* Socket C32 */
1138 dword = pci_read_config32(NODE_PCI(node, 0), 0x84);
1139 dword |= 0x1 << 13; /* LdtStopTriEn = 1 */
1140 pci_write_config32(NODE_PCI(node, 0), 0x84, dword);
1141
1142 dword = pci_read_config32(NODE_PCI(node, 0), 0xa4);
1143 dword |= 0x1 << 13; /* LdtStopTriEn = 1 */
1144 pci_write_config32(NODE_PCI(node, 0), 0xa4, dword);
1145
1146 dword = pci_read_config32(NODE_PCI(node, 0), 0xc4);
1147 dword |= 0x1 << 13; /* LdtStopTriEn = 1 */
1148 pci_write_config32(NODE_PCI(node, 0), 0xc4, dword);
1149
1150 dword = pci_read_config32(NODE_PCI(node, 0), 0xe4);
1151 dword |= 0x1 << 13; /* LdtStopTriEn = 1 */
1152 pci_write_config32(NODE_PCI(node, 0), 0xe4, dword);
1153 }
1154 else {
1155 /* Other socket (G34, etc.) */
1156 dword = pci_read_config32(NODE_PCI(node, 0), 0x84);
1157 dword &= ~(0x1 << 13); /* LdtStopTriEn = 0 */
1158 pci_write_config32(NODE_PCI(node, 0), 0x84, dword);
1159
1160 dword = pci_read_config32(NODE_PCI(node, 0), 0xa4);
1161 dword &= ~(0x1 << 13); /* LdtStopTriEn = 0 */
1162 pci_write_config32(NODE_PCI(node, 0), 0xa4, dword);
1163
1164 dword = pci_read_config32(NODE_PCI(node, 0), 0xc4);
1165 dword &= ~(0x1 << 13); /* LdtStopTriEn = 0 */
1166 pci_write_config32(NODE_PCI(node, 0), 0xc4, dword);
1167
1168 dword = pci_read_config32(NODE_PCI(node, 0), 0xe4);
1169 dword &= ~(0x1 << 13); /* LdtStopTriEn = 0 */
1170 pci_write_config32(NODE_PCI(node, 0), 0xe4, dword);
1171 }
1172 }
1173
Timothy Pearson0122afb2015-07-30 14:07:15 -05001174#ifdef DEBUG_HT_SETUP
1175 /* Dump link settings */
1176 for (i = 0; i < 4; i++) {
1177 for (j = 0; j < 4; j++) {
1178 printk(BIOS_DEBUG, "Node %d link %d: type register: %08x control register: %08x extended control sublink 0: %08x 1: %08x\n", i, j,
1179 pci_read_config32(NODE_PCI(i, 0), 0x98 + (j * 0x20)), pci_read_config32(NODE_PCI(i, 0), 0x84 + (j * 0x20)),
1180 pci_read_config32(NODE_PCI(i, 0), 0x170 + (j * 0x4)), pci_read_config32(NODE_PCI(i, 0), 0x180 + (j * 0x4)));
1181 }
1182 }
1183#endif
1184
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001185 for (i = 0; i < ARRAY_SIZE(fam10_htphy_default); i++) {
1186 if ((fam10_htphy_default[i].revision & revision) &&
1187 (fam10_htphy_default[i].platform & platform)) {
1188 /* HT Phy settings either apply to both sublinks or have
1189 * separate registers for sublink zero and one, so there
1190 * will be two table entries. So, here we only loop
1191 * through the sublink zeros in function zero.
1192 */
1193 for (j = 0; j < 4; j++) {
1194 if (AMD_CpuFindCapability(node, j, &offset)) {
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001195 if (AMD_checkLinkType(node, offset)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001196 & fam10_htphy_default[i].linktype) {
1197 AMD_SetHtPhyRegister(node, j,
1198 i);
1199 }
1200 } else {
1201 /* No more capabilities,
1202 * link not present
1203 */
1204 break;
1205 }
1206 }
1207 }
1208 }
1209
1210 /* FIXME: add UMA support and programXbarToSriReg(); */
1211
1212 AMD_Errata281(node, revision, platform);
1213
1214 /* FIXME: if the dct phy doesn't init correct it needs to reset.
1215 if (revision & (AMD_DR_B2 | AMD_DR_B3))
1216 dctPhyDiag(); */
1217
Timothy Pearson83abd812015-06-08 19:35:06 -05001218 if (revision & (AMD_DR_GT_D0 | AMD_FAM15_ALL)) {
1219 /* Set up message triggered C1E */
1220 dword = pci_read_config32(NODE_PCI(node, 3), 0xd4);
1221 dword &= ~(0x1 << 14); /* CacheFlushImmOnAllHalt = !is_fam15h() */
1222 dword |= (is_fam15h()?0:1) << 14;
1223 pci_write_config32(NODE_PCI(node, 3), 0xd4, dword);
1224
1225 dword = pci_read_config32(NODE_PCI(node, 3), 0xdc);
1226 dword |= 0x1 << 26; /* IgnCpuPrbEn = 1 */
1227 dword &= ~(0x7f << 19); /* CacheFlushOnHaltTmr = 0x28 */
1228 dword |= 0x28 << 19;
1229 dword |= 0x7 << 16; /* CacheFlushOnHaltCtl = 0x7 */
1230 pci_write_config32(NODE_PCI(node, 3), 0xdc, dword);
1231
1232 dword = pci_read_config32(NODE_PCI(node, 3), 0xa0);
1233 dword |= 0x1 << 10; /* IdleExitEn = 1 */
1234 pci_write_config32(NODE_PCI(node, 3), 0xa0, dword);
1235
1236 if (revision & AMD_DR_GT_D0) {
1237 dword = pci_read_config32(NODE_PCI(node, 3), 0x188);
1238 dword |= 0x1 << 4; /* EnStpGntOnFlushMaskWakeup = 1 */
1239 pci_write_config32(NODE_PCI(node, 3), 0x188, dword);
1240 } else {
1241 dword = pci_read_config32(NODE_PCI(node, 4), 0x128);
1242 dword &= ~(0x1 << 31); /* CstateMsgDis = 0 */
1243 pci_write_config32(NODE_PCI(node, 4), 0x128, dword);
1244 }
1245
1246 dword = pci_read_config32(NODE_PCI(node, 3), 0xd4);
1247 dword |= 0x1 << 13; /* MTC1eEn = 1 */
1248 pci_write_config32(NODE_PCI(node, 3), 0xd4, dword);
1249 }
1250
Timothy Pearson965704a2015-08-07 19:04:49 -05001251 if (revision & AMD_FAM15_ALL) {
1252 uint32_t f5x80;
1253 uint8_t cu_enabled;
1254 uint8_t compute_unit_count = 0;
1255 uint8_t compute_unit_buffer_count;
1256
Timothy Pearson71b8f012015-08-07 23:59:17 -05001257 uint32_t f3xe8;
1258 uint8_t dual_node = 0;
1259
1260 f3xe8 = pci_read_config32(NODE_PCI(0, 3), 0xe8);
1261
1262 /* Check for dual node capability */
1263 if (f3xe8 & 0x20000000)
1264 dual_node = 1;
1265
Timothy Pearson965704a2015-08-07 19:04:49 -05001266 /* Determine the number of active compute units on this node */
1267 f5x80 = pci_read_config32(NODE_PCI(node, 5), 0x80);
1268 cu_enabled = f5x80 & 0xf;
1269 if (cu_enabled == 0x1)
1270 compute_unit_count = 1;
1271 if (cu_enabled == 0x3)
1272 compute_unit_count = 2;
1273 if (cu_enabled == 0x7)
1274 compute_unit_count = 3;
1275 if (cu_enabled == 0xf)
1276 compute_unit_count = 4;
1277
1278 if (compute_unit_count == 1)
1279 compute_unit_buffer_count = 0x1c;
1280 else if (compute_unit_count == 2)
1281 compute_unit_buffer_count = 0x18;
1282 else if (compute_unit_count == 3)
1283 compute_unit_buffer_count = 0x14;
1284 else
1285 compute_unit_buffer_count = 0x10;
1286
1287 dword = pci_read_config32(NODE_PCI(node, 3), 0x1a0);
1288 dword &= ~(0x1f << 4); /* L3FreeListCBC = compute_unit_buffer_count */
1289 dword |= (compute_unit_buffer_count << 4);
1290 pci_write_config32(NODE_PCI(node, 3), 0x1a0, dword);
Timothy Pearson71b8f012015-08-07 23:59:17 -05001291
Timothy Pearsona52d5d12015-08-08 20:30:36 -05001292 uint8_t link;
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001293 uint8_t link_real;
Timothy Pearsona52d5d12015-08-08 20:30:36 -05001294 uint8_t ganged;
1295 uint8_t iolink;
1296 uint8_t probe_filter_enabled = !!dual_node;
1297
1298 /* Set up the Link Base Channel Buffer Count */
1299 uint8_t isoc_rsp_data;
1300 uint8_t isoc_np_req_data;
1301 uint8_t isoc_rsp_cmd;
1302 uint8_t isoc_preq;
1303 uint8_t isoc_np_req_cmd;
1304 uint8_t free_data;
1305 uint8_t free_cmd;
1306 uint8_t rsp_data;
1307 uint8_t np_req_data;
1308 uint8_t probe_cmd;
1309 uint8_t rsp_cmd;
1310 uint8_t preq;
1311 uint8_t np_req_cmd;
1312
1313 /* Common settings for all links and system configurations */
1314 isoc_rsp_data = 0;
1315 isoc_np_req_data = 0;
1316 isoc_rsp_cmd = 0;
1317 isoc_preq = 0;
1318 isoc_np_req_cmd = 1;
1319 free_cmd = 8;
1320
1321 for (link = 0; link < 4; link++) {
1322 if (AMD_CpuFindCapability(node, link, &offset)) {
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001323 link_real = (offset - 0x80) / 0x20;
1324 ganged = !!(pci_read_config32(NODE_PCI(node, 0), (link_real << 2) + 0x170) & 0x1);
1325 iolink = !!(AMD_checkLinkType(node, offset) & HTPHY_LINKTYPE_NONCOHERENT);
Timothy Pearsona52d5d12015-08-08 20:30:36 -05001326
1327 if (!iolink && ganged) {
1328 if (probe_filter_enabled) {
1329 free_data = 0;
1330 rsp_data = 3;
1331 np_req_data = 3;
1332 probe_cmd = 4;
1333 rsp_cmd = 9;
1334 preq = 2;
1335 np_req_cmd = 8;
1336 } else {
1337 free_data = 0;
1338 rsp_data = 3;
1339 np_req_data = 3;
1340 probe_cmd = 8;
1341 rsp_cmd = 9;
1342 preq = 2;
1343 np_req_cmd = 4;
1344 }
1345 } else if (!iolink && !ganged) {
1346 if (probe_filter_enabled) {
1347 free_data = 0;
1348 rsp_data = 3;
1349 np_req_data = 3;
1350 probe_cmd = 4;
1351 rsp_cmd = 9;
1352 preq = 2;
1353 np_req_cmd = 8;
1354 } else {
1355 free_data = 0;
1356 rsp_data = 3;
1357 np_req_data = 3;
1358 probe_cmd = 8;
1359 rsp_cmd = 9;
1360 preq = 2;
1361 np_req_cmd = 4;
1362 }
1363 } else if (iolink && ganged) {
1364 free_data = 0;
1365 rsp_data = 1;
1366 np_req_data = 0;
1367 probe_cmd = 0;
1368 rsp_cmd = 2;
1369 preq = 7;
1370 np_req_cmd = 14;
1371 } else {
1372 /* FIXME
1373 * This is an educated guess as the BKDG does not specify
1374 * the appropriate buffer counts for this case!
1375 */
1376 free_data = 1;
1377 rsp_data = 1;
1378 np_req_data = 1;
1379 probe_cmd = 0;
1380 rsp_cmd = 2;
1381 preq = 4;
1382 np_req_cmd = 12;
1383 }
1384
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001385 dword = pci_read_config32(NODE_PCI(node, 0), (link_real * 0x20) + 0x94);
Timothy Pearsona52d5d12015-08-08 20:30:36 -05001386 dword &= ~(0x3 << 27); /* IsocRspData = isoc_rsp_data */
1387 dword |= ((isoc_rsp_data & 0x3) << 27);
1388 dword &= ~(0x3 << 25); /* IsocNpReqData = isoc_np_req_data */
1389 dword |= ((isoc_np_req_data & 0x3) << 25);
1390 dword &= ~(0x7 << 22); /* IsocRspCmd = isoc_rsp_cmd */
1391 dword |= ((isoc_rsp_cmd & 0x7) << 22);
1392 dword &= ~(0x7 << 19); /* IsocPReq = isoc_preq */
1393 dword |= ((isoc_preq & 0x7) << 19);
1394 dword &= ~(0x7 << 16); /* IsocNpReqCmd = isoc_np_req_cmd */
1395 dword |= ((isoc_np_req_cmd & 0x7) << 16);
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001396 pci_write_config32(NODE_PCI(node, 0), (link_real * 0x20) + 0x94, dword);
Timothy Pearsona52d5d12015-08-08 20:30:36 -05001397
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001398 dword = pci_read_config32(NODE_PCI(node, 0), (link_real * 0x20) + 0x90);
Timothy Pearsona52d5d12015-08-08 20:30:36 -05001399 dword &= ~(0x1 << 31); /* LockBc = 0x1 */
1400 dword |= ((0x1 & 0x1) << 31);
1401 dword &= ~(0x7 << 25); /* FreeData = free_data */
1402 dword |= ((free_data & 0x7) << 25);
1403 dword &= ~(0x1f << 20); /* FreeCmd = free_cmd */
1404 dword |= ((free_cmd & 0x1f) << 20);
1405 dword &= ~(0x3 << 18); /* RspData = rsp_data */
1406 dword |= ((rsp_data & 0x3) << 18);
1407 dword &= ~(0x3 << 16); /* NpReqData = np_req_data */
1408 dword |= ((np_req_data & 0x3) << 16);
1409 dword &= ~(0xf << 12); /* ProbeCmd = probe_cmd */
1410 dword |= ((probe_cmd & 0xf) << 12);
1411 dword &= ~(0xf << 8); /* RspCmd = rsp_cmd */
1412 dword |= ((rsp_cmd & 0xf) << 8);
1413 dword &= ~(0x7 << 5); /* PReq = preq */
1414 dword |= ((preq & 0x7) << 5);
1415 dword &= ~(0x1f << 0); /* NpReqCmd = np_req_cmd */
1416 dword |= ((np_req_cmd & 0x1f) << 0);
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001417 pci_write_config32(NODE_PCI(node, 0), (link_real * 0x20) + 0x90, dword);
Timothy Pearsona52d5d12015-08-08 20:30:36 -05001418 }
1419 }
1420
Timothy Pearson71b8f012015-08-07 23:59:17 -05001421 /* Set up the Link to XCS Token Counts */
1422 uint8_t isoc_rsp_tok_1;
1423 uint8_t isoc_preq_tok_1;
1424 uint8_t isoc_req_tok_1;
1425 uint8_t probe_tok_1;
1426 uint8_t rsp_tok_1;
1427 uint8_t preq_tok_1;
1428 uint8_t req_tok_1;
1429 uint8_t isoc_rsp_tok_0;
1430 uint8_t isoc_preq_tok_0;
1431 uint8_t isoc_req_tok_0;
1432 uint8_t free_tokens;
1433 uint8_t probe_tok_0;
1434 uint8_t rsp_tok_0;
1435 uint8_t preq_tok_0;
1436 uint8_t req_tok_0;
1437
Timothy Pearson71b8f012015-08-07 23:59:17 -05001438 for (link = 0; link < 4; link++) {
1439 if (AMD_CpuFindCapability(node, link, &offset)) {
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001440 link_real = (offset - 0x80) / 0x20;
1441 ganged = !!(pci_read_config32(NODE_PCI(node, 0), (link_real << 2) + 0x170) & 0x1);
1442 iolink = !!(AMD_checkLinkType(node, offset) & HTPHY_LINKTYPE_NONCOHERENT);
Timothy Pearson71b8f012015-08-07 23:59:17 -05001443
1444 /* Set defaults */
1445 isoc_rsp_tok_1 = 0;
1446 isoc_preq_tok_1 = 0;
1447 isoc_req_tok_1 = 0;
1448 probe_tok_1 = !ganged;
1449 rsp_tok_1 = !ganged;
1450 preq_tok_1 = !ganged;
1451 req_tok_1 = !ganged;
1452 isoc_rsp_tok_0 = 0;
1453 isoc_preq_tok_0 = 0;
1454 isoc_req_tok_0 = 0;
1455 free_tokens = 0;
1456 probe_tok_0 = ((ganged)?2:1);
1457 rsp_tok_0 = ((ganged)?2:1);
1458 preq_tok_0 = ((ganged)?2:1);
1459 req_tok_0 = ((ganged)?2:1);
1460
1461 if (!iolink && ganged) {
1462 if (!dual_node) {
1463 isoc_rsp_tok_1 = 0;
1464 isoc_preq_tok_1 = 0;
1465 isoc_req_tok_1 = 0;
1466 probe_tok_1 = 0;
1467 rsp_tok_1 = 0;
1468 preq_tok_1 = 0;
1469 req_tok_1 = 0;
1470 isoc_rsp_tok_0 = 0;
1471 isoc_preq_tok_0 = 0;
1472 isoc_req_tok_0 = 1;
1473 free_tokens = 3;
1474 probe_tok_0 = 2;
1475 rsp_tok_0 = 2;
1476 preq_tok_0 = 2;
1477 req_tok_0 = 2;
1478 } else {
1479 if ((sockets == 1)
1480 || ((sockets == 2) && (sockets_populated == 1))) {
1481 isoc_rsp_tok_1 = 0;
1482 isoc_preq_tok_1 = 0;
1483 isoc_req_tok_1 = 0;
1484 probe_tok_1 = 0;
1485 rsp_tok_1 = 0;
1486 preq_tok_1 = 0;
1487 req_tok_1 = 0;
1488 isoc_rsp_tok_0 = 0;
1489 isoc_preq_tok_0 = 0;
1490 isoc_req_tok_0 = 1;
1491 free_tokens = 0;
1492 probe_tok_0 = 2;
1493 rsp_tok_0 = 2;
1494 preq_tok_0 = 2;
1495 req_tok_0 = 2;
1496 } else if (((sockets == 2) && (sockets_populated == 2))
1497 || ((sockets == 4) && (sockets_populated == 2))) {
1498 isoc_rsp_tok_1 = 0;
1499 isoc_preq_tok_1 = 0;
1500 isoc_req_tok_1 = 0;
1501 probe_tok_1 = 0;
1502 rsp_tok_1 = 0;
1503 preq_tok_1 = 0;
1504 req_tok_1 = 0;
1505 isoc_rsp_tok_0 = 0;
1506 isoc_preq_tok_0 = 0;
1507 isoc_req_tok_0 = 1;
1508 free_tokens = 0;
1509 probe_tok_0 = 1;
1510 rsp_tok_0 = 2;
1511 preq_tok_0 = 2;
1512 req_tok_0 = 2;
1513 } else if ((sockets == 4) && (sockets_populated == 4)) {
1514 isoc_rsp_tok_1 = 0;
1515 isoc_preq_tok_1 = 0;
1516 isoc_req_tok_1 = 0;
1517 probe_tok_1 = 0;
1518 rsp_tok_1 = 0;
1519 preq_tok_1 = 0;
1520 req_tok_1 = 0;
1521 isoc_rsp_tok_0 = 0;
1522 isoc_preq_tok_0 = 0;
1523 isoc_req_tok_0 = 1;
1524 free_tokens = 0;
1525 probe_tok_0 = 2;
1526 rsp_tok_0 = 1;
1527 preq_tok_0 = 1;
1528 req_tok_0 = 2;
1529 }
1530 }
1531 } else if (!iolink && !ganged) {
1532 if ((sockets == 1)
1533 || ((sockets == 2) && (sockets_populated == 1))) {
1534 if (probe_filter_enabled) {
1535 isoc_rsp_tok_1 = 0;
1536 isoc_preq_tok_1 = 0;
1537 isoc_req_tok_1 = 0;
1538 probe_tok_1 = 1;
1539 rsp_tok_1 = 1;
1540 preq_tok_1 = 1;
1541 req_tok_1 = 1;
1542 isoc_rsp_tok_0 = 0;
1543 isoc_preq_tok_0 = 0;
1544 isoc_req_tok_0 = 1;
1545 free_tokens = 0;
1546 probe_tok_0 = 1;
1547 rsp_tok_0 = 2;
1548 preq_tok_0 = 1;
1549 req_tok_0 = 1;
1550 } else {
1551 isoc_rsp_tok_1 = 0;
1552 isoc_preq_tok_1 = 0;
1553 isoc_req_tok_1 = 0;
1554 probe_tok_1 = 1;
1555 rsp_tok_1 = 1;
1556 preq_tok_1 = 1;
1557 req_tok_1 = 1;
1558 isoc_rsp_tok_0 = 0;
1559 isoc_preq_tok_0 = 0;
1560 isoc_req_tok_0 = 1;
1561 free_tokens = 0;
1562 probe_tok_0 = 1;
1563 rsp_tok_0 = 1;
1564 preq_tok_0 = 1;
1565 req_tok_0 = 1;
1566 }
1567 } else if ((sockets == 2) && (sockets_populated == 2)) {
1568 isoc_rsp_tok_1 = 0;
1569 isoc_preq_tok_1 = 0;
1570 isoc_req_tok_1 = 1;
1571 probe_tok_1 = 1;
1572 rsp_tok_1 = 1;
1573 preq_tok_1 = 1;
1574 req_tok_1 = 1;
1575 isoc_rsp_tok_0 = 0;
1576 isoc_preq_tok_0 = 0;
1577 isoc_req_tok_0 = 1;
1578 free_tokens = 2;
1579 probe_tok_0 = 1;
1580 rsp_tok_0 = 1;
1581 preq_tok_0 = 1;
1582 req_tok_0 = 1;
1583 } else if ((sockets == 4) && (sockets_populated == 2)) {
1584 isoc_rsp_tok_1 = 0;
1585 isoc_preq_tok_1 = 0;
1586 isoc_req_tok_1 = 1;
1587 probe_tok_1 = 1;
1588 rsp_tok_1 = 1;
1589 preq_tok_1 = 1;
1590 req_tok_1 = 1;
1591 isoc_rsp_tok_0 = 0;
1592 isoc_preq_tok_0 = 0;
1593 isoc_req_tok_0 = 1;
1594 free_tokens = 4;
1595 probe_tok_0 = 1;
1596 rsp_tok_0 = 1;
1597 preq_tok_0 = 1;
1598 req_tok_0 = 1;
1599 } else if ((sockets == 4) && (sockets_populated == 4)) {
1600 isoc_rsp_tok_1 = 0;
1601 isoc_preq_tok_1 = 0;
1602 isoc_req_tok_1 = 1;
1603 probe_tok_1 = 1;
1604 rsp_tok_1 = 1;
1605 preq_tok_1 = 1;
1606 req_tok_1 = 1;
1607 isoc_rsp_tok_0 = 0;
1608 isoc_preq_tok_0 = 0;
1609 isoc_req_tok_0 = 1;
1610 free_tokens = 0;
1611 probe_tok_0 = 1;
1612 rsp_tok_0 = 1;
1613 preq_tok_0 = 1;
1614 req_tok_0 = 1;
1615 }
1616 } else if (iolink && ganged) {
1617 if (!dual_node) {
1618 isoc_rsp_tok_1 = 0;
1619 isoc_preq_tok_1 = 0;
1620 isoc_req_tok_1 = 0;
1621 probe_tok_1 = 0;
1622 rsp_tok_1 = 0;
1623 preq_tok_1 = 0;
1624 req_tok_1 = 0;
1625 isoc_rsp_tok_0 = 0;
1626 isoc_preq_tok_0 = 0;
1627 isoc_req_tok_0 = 1;
1628 free_tokens = 3;
1629 probe_tok_0 = 0;
1630 rsp_tok_0 = 2;
1631 preq_tok_0 = 2;
1632 req_tok_0 = 2;
1633 } else if ((sockets == 1)
1634 || (sockets == 2)
1635 || ((sockets == 4) && (sockets_populated == 2))) {
1636 isoc_rsp_tok_1 = 0;
1637 isoc_preq_tok_1 = 0;
1638 isoc_req_tok_1 = 0;
1639 probe_tok_1 = 0;
1640 rsp_tok_1 = 0;
1641 preq_tok_1 = 0;
1642 req_tok_1 = 0;
1643 isoc_rsp_tok_0 = 0;
1644 isoc_preq_tok_0 = 0;
1645 isoc_req_tok_0 = 1;
1646 free_tokens = 0;
1647 probe_tok_0 = 0;
1648 rsp_tok_0 = 2;
1649 preq_tok_0 = 2;
1650 req_tok_0 = 2;
1651 } else if ((sockets == 4) && (sockets_populated == 4)) {
1652 isoc_rsp_tok_1 = 0;
1653 isoc_preq_tok_1 = 0;
1654 isoc_req_tok_1 = 0;
1655 probe_tok_1 = 0;
1656 rsp_tok_1 = 0;
1657 preq_tok_1 = 0;
1658 req_tok_1 = 0;
1659 isoc_rsp_tok_0 = 0;
1660 isoc_preq_tok_0 = 0;
1661 isoc_req_tok_0 = 2;
1662 free_tokens = 0;
1663 probe_tok_0 = 2;
1664 rsp_tok_0 = 2;
1665 preq_tok_0 = 2;
1666 req_tok_0 = 2;
1667 }
1668 }
1669
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001670 dword = pci_read_config32(NODE_PCI(node, 3), (link_real << 2) + 0x148);
Timothy Pearson71b8f012015-08-07 23:59:17 -05001671 dword &= ~(0x3 << 30); /* FreeTok[3:2] = free_tokens[3:2] */
1672 dword |= (((free_tokens >> 2) & 0x3) << 30);
1673 dword &= ~(0x1 << 28); /* IsocRspTok1 = isoc_rsp_tok_1 */
1674 dword |= (((isoc_rsp_tok_1) & 0x1) << 28);
1675 dword &= ~(0x1 << 26); /* IsocPreqTok1 = isoc_preq_tok_1 */
1676 dword |= (((isoc_preq_tok_1) & 0x1) << 26);
1677 dword &= ~(0x1 << 24); /* IsocReqTok1 = isoc_req_tok_1 */
1678 dword |= (((isoc_req_tok_1) & 0x1) << 24);
1679 dword &= ~(0x3 << 22); /* ProbeTok1 = probe_tok_1 */
1680 dword |= (((probe_tok_1) & 0x3) << 22);
1681 dword &= ~(0x3 << 20); /* RspTok1 = rsp_tok_1 */
1682 dword |= (((rsp_tok_1) & 0x3) << 20);
1683 dword &= ~(0x3 << 18); /* PReqTok1 = preq_tok_1 */
1684 dword |= (((preq_tok_1) & 0x3) << 18);
1685 dword &= ~(0x3 << 16); /* ReqTok1 = req_tok_1 */
1686 dword |= (((req_tok_1) & 0x3) << 16);
1687 dword &= ~(0x3 << 14); /* FreeTok[1:0] = free_tokens[1:0] */
1688 dword |= (((free_tokens) & 0x3) << 14);
1689 dword &= ~(0x3 << 12); /* IsocRspTok0 = isoc_rsp_tok_0 */
1690 dword |= (((isoc_rsp_tok_0) & 0x3) << 12);
1691 dword &= ~(0x3 << 10); /* IsocPreqTok0 = isoc_preq_tok_0 */
1692 dword |= (((isoc_preq_tok_0) & 0x3) << 10);
1693 dword &= ~(0x3 << 8); /* IsocReqTok0 = isoc_req_tok_0 */
1694 dword |= (((isoc_req_tok_0) & 0x3) << 8);
1695 dword &= ~(0x3 << 6); /* ProbeTok0 = probe_tok_0 */
1696 dword |= (((probe_tok_0) & 0x3) << 6);
1697 dword &= ~(0x3 << 4); /* RspTok0 = rsp_tok_0 */
1698 dword |= (((rsp_tok_0) & 0x3) << 4);
1699 dword &= ~(0x3 << 2); /* PReqTok0 = preq_tok_0 */
1700 dword |= (((preq_tok_0) & 0x3) << 2);
1701 dword &= ~(0x3 << 0); /* ReqTok0 = req_tok_0 */
1702 dword |= (((req_tok_0) & 0x3) << 0);
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001703 pci_write_config32(NODE_PCI(node, 3), (link_real << 2) + 0x148, dword);
Timothy Pearson71b8f012015-08-07 23:59:17 -05001704 }
1705 }
Timothy Pearsonbaa1acd2015-08-08 22:14:59 -05001706
1707 /* Set up the SRI to XCS Token Count */
1708 uint8_t free_tok;
1709 uint8_t up_rsp_tok;
1710
1711 /* Set defaults */
1712 free_tok = 0xa;
1713 up_rsp_tok = 0x3;
1714
1715 if (!dual_node) {
1716 free_tok = 0xa;
1717 up_rsp_tok = 0x3;
1718 } else {
1719 if ((sockets == 1)
1720 || ((sockets == 2) && (sockets_populated == 1))) {
1721 if (probe_filter_enabled) {
1722 free_tok = 0x9;
1723 up_rsp_tok = 0x3;
1724 } else {
1725 free_tok = 0xa;
1726 up_rsp_tok = 0x3;
1727 }
1728 } else if ((sockets == 2) && (sockets_populated == 2)) {
1729 free_tok = 0xb;
1730 up_rsp_tok = 0x1;
1731 } else if ((sockets == 4) && (sockets_populated == 2)) {
1732 free_tok = 0xa;
1733 up_rsp_tok = 0x3;
1734 } else if ((sockets == 4) && (sockets_populated == 4)) {
1735 free_tok = 0x9;
1736 up_rsp_tok = 0x1;
1737 }
1738 }
1739
1740 dword = pci_read_config32(NODE_PCI(node, 3), 0x140);
1741 dword &= ~(0xf << 20); /* FreeTok = free_tok */
1742 dword |= ((free_tok & 0xf) << 20);
1743 dword &= ~(0x3 << 8); /* UpRspTok = up_rsp_tok */
1744 dword |= ((up_rsp_tok & 0x3) << 8);
1745 pci_write_config32(NODE_PCI(node, 3), 0x140, dword);
Timothy Pearson965704a2015-08-07 19:04:49 -05001746 }
1747
Timothy Pearson50001b82015-08-11 17:47:48 -05001748 uint8_t link;
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001749 uint8_t link_real;
Timothy Pearson50001b82015-08-11 17:47:48 -05001750 uint8_t isochronous;
1751 uint8_t isochronous_link_present;
1752
1753 /* Set up isochronous buffers if needed */
1754 isochronous_link_present = 0;
1755 if (revision & AMD_FAM15_ALL) {
1756 for (link = 0; link < 4; link++) {
1757 if (AMD_CpuFindCapability(node, link, &offset)) {
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001758 link_real = (offset - 0x80) / 0x20;
1759 isochronous = (pci_read_config32(NODE_PCI(node, 0), (link_real * 0x20) + 0x84) >> 12) & 0x1;
Timothy Pearson50001b82015-08-11 17:47:48 -05001760
1761 if (isochronous)
1762 isochronous_link_present = 1;
1763 }
1764 }
1765 }
1766
1767 uint8_t free_tok;
1768 uint8_t up_rsp_cbc;
1769 uint8_t isoc_preq_cbc;
1770 uint8_t isoc_preq_tok;
1771 uint8_t xbar_to_sri_free_list_cbc;
1772 if (isochronous_link_present) {
1773 /* Adjust buffer counts */
1774 dword = pci_read_config32(NODE_PCI(node, 3), 0x70);
1775 isoc_preq_cbc = (dword >> 24) & 0x7;
1776 up_rsp_cbc = (dword >> 16) & 0x7;
1777 up_rsp_cbc--;
1778 isoc_preq_cbc++;
1779 dword &= ~(0x7 << 24); /* IsocPreqCBC = isoc_preq_cbc */
1780 dword |= ((isoc_preq_cbc & 0x7) << 24);
1781 dword &= ~(0x7 << 16); /* UpRspCBC = up_rsp_cbc */
1782 dword |= ((up_rsp_cbc & 0x7) << 16);
1783 pci_write_config32(NODE_PCI(node, 3), 0x70, dword);
1784
1785 dword = pci_read_config32(NODE_PCI(node, 3), 0x74);
1786 isoc_preq_cbc = (dword >> 24) & 0x7;
1787 isoc_preq_cbc++;
1788 dword &= ~(0x7 << 24); /* IsocPreqCBC = isoc_preq_cbc */
1789 dword |= (isoc_preq_cbc & 0x7) << 24;
1790 pci_write_config32(NODE_PCI(node, 3), 0x74, dword);
1791
1792 dword = pci_read_config32(NODE_PCI(node, 3), 0x7c);
1793 xbar_to_sri_free_list_cbc = dword & 0x1f;
1794 xbar_to_sri_free_list_cbc--;
1795 dword &= ~0x1f; /* Xbar2SriFreeListCBC = xbar_to_sri_free_list_cbc */
1796 dword |= xbar_to_sri_free_list_cbc & 0x1f;
1797 pci_write_config32(NODE_PCI(node, 3), 0x7c, dword);
1798
1799 dword = pci_read_config32(NODE_PCI(node, 3), 0x140);
1800 free_tok = (dword >> 20) & 0xf;
1801 isoc_preq_tok = (dword >> 14) & 0x3;
1802 free_tok--;
1803 isoc_preq_tok++;
1804 dword &= ~(0xf << 20); /* FreeTok = free_tok */
1805 dword |= ((free_tok & 0xf) << 20);
1806 dword &= ~(0x3 << 14); /* IsocPreqTok = isoc_preq_tok */
1807 dword |= ((isoc_preq_tok & 0x3) << 14);
1808 pci_write_config32(NODE_PCI(node, 3), 0x140, dword);
1809 }
1810
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001811 printk(BIOS_DEBUG, " done\n");
1812}
1813
1814#ifdef UNUSED_CODE
Timothy Pearson730a0432015-10-16 13:51:51 -05001815/* Clearing the MCA registers is apparently handled in the ramstage CPU Function 3 driver */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001816static void cpuInitializeMCA(void)
1817{
1818 /* Clears Machine Check Architecture (MCA) registers, which power on
1819 * containing unknown data, on currently running processor.
1820 * This routine should only be executed on initial power on (cold boot),
1821 * not across a warm reset because valid data is present at that time.
1822 */
1823
1824 msr_t msr;
1825 u32 reg;
1826 u8 i;
1827
1828 if (cpuid_edx(1) & 0x4080) { /* MCE and MCA (edx[7] and edx[14]) */
1829 msr = rdmsr(MCG_CAP);
1830 if (msr.lo & MCG_CTL_P) { /* MCG_CTL_P bit is set? */
1831 msr.lo &= 0xFF;
1832 msr.lo--;
1833 msr.lo <<= 2; /* multiply the count by 4 */
1834 reg = MC0_STA + msr.lo;
1835 msr.lo = msr.hi = 0;
1836 for (i = 0; i < 4; i++) {
1837 wrmsr(reg, msr);
1838 reg -= 4; /* Touch status regs for each bank */
1839 }
1840 }
1841 }
1842}
1843#endif
1844
1845/**
1846 * finalize_node_setup()
1847 *
1848 * Do any additional post HT init
1849 *
1850 */
Damien Zammit75a3d1f2016-11-28 00:29:10 +11001851void finalize_node_setup(struct sys_info *sysinfo)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001852{
1853 u8 i;
1854 u8 nodes = get_nodes();
Patrick Georgif3e85422010-10-26 15:11:45 +00001855 u32 reg;
Kyösti Mälkki239c3d32013-12-27 14:46:32 +02001856
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001857 /* read Node0 F0_0x64 bit [8:10] to find out SbLink # */
1858 reg = pci_read_config32(NODE_HT(0), 0x64);
1859 sysinfo->sblk = (reg >> 8) & 7;
1860 sysinfo->sbbusn = 0;
1861 sysinfo->nodes = nodes;
1862 sysinfo->sbdn = get_sbdn(sysinfo->sbbusn);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001863
1864 for (i = 0; i < nodes; i++) {
1865 cpuSetAMDPCI(i);
1866 }
1867
Martin Roth5f46af62017-06-24 13:24:26 -06001868#if IS_ENABLED(CONFIG_SET_FIDVID)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001869 // Prep each node for FID/VID setup.
1870 prep_fid_change();
1871#endif
1872
1873#if CONFIG_MAX_PHYSICAL_CPUS > 1
1874 /* Skip the BSP, start at node 1 */
1875 for (i = 1; i < nodes; i++) {
1876 setup_remote_node(i);
1877 start_node(i);
1878 }
1879#endif
1880}
1881
Damien Zammit75a3d1f2016-11-28 00:29:10 +11001882#if IS_ENABLED(CONFIG_SET_FIDVID)
1883# include "fidvid.c"
1884#endif