blob: bf1862b7e94e8750abada2e99f927c17171481e8 [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
Kyösti Mälkki142b52c2013-12-10 07:33:36 +020017#include "cpu/amd/car/post_cache_as_ram.c"
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000018#include "defaults.h"
19#include <stdlib.h>
20#include <cpu/x86/lapic.h>
21#include <cpu/x86/mtrr.h>
22#include <northbridge/amd/amdfam10/amdfam10.h>
23#include <northbridge/amd/amdht/AsPsDefs.h>
24#include <northbridge/amd/amdht/porting.h>
25
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000026#include <northbridge/amd/amdfam10/raminit_amdmct.c>
Kerry She799fed92011-01-01 17:44:07 +000027#include <reset.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
Timothy Pearson730a0432015-10-16 13:51:51 -050037#if IS_ENABLED(CONFIG_SET_FIDVID)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000038static void prep_fid_change(void);
39static void init_fidvid_stage2(u32 apicid, u32 nodeid);
Timothy Pearson730a0432015-10-16 13:51:51 -050040#endif
41
42void cpuSetAMDMSR(uint8_t node_id);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000043
Patrick Georgie1667822012-05-05 15:29:32 +020044#if CONFIG_PCI_IO_CFG_EXT
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000045static void set_EnableCf8ExtCfg(void)
46{
47 // set the NB_CFG[46]=1;
48 msr_t msr;
49 msr = rdmsr(NB_CFG_MSR);
50 // EnableCf8ExtCfg: We need that to access CONFIG_PCI_IO_CFG_EXT 4K range
51 msr.hi |= (1 << (46 - 32));
52 wrmsr(NB_CFG_MSR, msr);
53}
54#else
55static void set_EnableCf8ExtCfg(void) { }
56#endif
57
Timothy Pearson0122afb2015-07-30 14:07:15 -050058// #define DEBUG_HT_SETUP 1
59// #define FAM10_AP_NODE_SEQUENTIAL_START 1
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000060
61typedef void (*process_ap_t) (u32 apicid, void *gp);
62
Timothy Pearson730a0432015-10-16 13:51:51 -050063uint32_t get_boot_apic_id(uint8_t node, uint32_t core) {
64 uint32_t ap_apicid;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000065
Timothy Pearson730a0432015-10-16 13:51:51 -050066 uint32_t nb_cfg_54;
67 uint32_t siblings;
68 uint32_t cores_found;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000069
Timothy Pearson730a0432015-10-16 13:51:51 -050070 uint8_t fam15h = 0;
Timothy Pearson1c4508e2015-09-05 17:50:29 -050071 uint8_t rev_gte_d = 0;
72 uint8_t dual_node = 0;
73 uint32_t f3xe8;
Timothy Pearson730a0432015-10-16 13:51:51 -050074 uint32_t family;
75 uint32_t model;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000076
Timothy Pearson730a0432015-10-16 13:51:51 -050077 uint32_t ApicIdCoreIdSize;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +000078
79 /* Assume that all node are same stepping, otherwise we can use use
80 nb_cfg_54 from bsp for all nodes */
81 nb_cfg_54 = read_nb_cfg_54();
Timothy Pearson1c4508e2015-09-05 17:50:29 -050082 f3xe8 = pci_read_config32(NODE_PCI(0, 3), 0xe8);
83
Timothy Pearson730a0432015-10-16 13:51:51 -050084 family = model = cpuid_eax(0x80000001);
85 model = ((model & 0xf0000) >> 12) | ((model & 0xf0) >> 4);
86 family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);
87
88 if (family >= 0x6f) {
89 /* Family 15h or later */
90 fam15h = 1;
91 nb_cfg_54 = 1;
92 }
93
94 if ((model >= 0x8) || fam15h)
Timothy Pearson1c4508e2015-09-05 17:50:29 -050095 /* Revision D or later */
96 rev_gte_d = 1;
97
98 if (rev_gte_d)
99 /* Check for dual node capability */
100 if (f3xe8 & 0x20000000)
101 dual_node = 1;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000102
103 ApicIdCoreIdSize = (cpuid_ecx(0x80000008) >> 12 & 0xf);
104 if (ApicIdCoreIdSize) {
105 siblings = ((1 << ApicIdCoreIdSize) - 1);
106 } else {
107 siblings = 3; //quad core
108 }
109
Timothy Pearson730a0432015-10-16 13:51:51 -0500110 cores_found = get_core_num_in_bsp(node);
111 if (siblings > cores_found)
112 siblings = cores_found;
113
114 if (dual_node) {
115 ap_apicid = 0;
116 if (fam15h) {
117 ap_apicid |= ((node >> 1) & 0x3) << 5; /* Node ID */
118 ap_apicid |= ((node & 0x1) * (siblings + 1)) + core; /* Core ID */
119 } else {
120 if (nb_cfg_54) {
121 ap_apicid |= ((node >> 1) & 0x3) << 4; /* Node ID */
122 ap_apicid |= ((node & 0x1) * (siblings + 1)) + core; /* Core ID */
123 } else {
124 ap_apicid |= node & 0x3; /* Node ID */
125 ap_apicid |= (((node & 0x1) * (siblings + 1)) + core) << 4; /* Core ID */
126 }
127 }
128 } else {
129 if (fam15h) {
130 ap_apicid = (node * (siblings + 1)) + core;
131 } else {
132 ap_apicid = node * (nb_cfg_54 ? (siblings + 1) : 1) +
133 core * (nb_cfg_54 ? 1 : 64);
134 }
135 }
136
137 return ap_apicid;
138}
139
140//core_range = 0 : all cores
141//core range = 1 : core 0 only
142//core range = 2 : cores other than core0
143
Timothy Pearson0122afb2015-07-30 14:07:15 -0500144static void for_each_ap(uint32_t bsp_apicid, uint32_t core_range, int8_t node,
145 process_ap_t process_ap, void *gp)
Timothy Pearson730a0432015-10-16 13:51:51 -0500146{
147 // here assume the OS don't change our apicid
148 u32 ap_apicid;
149
150 u32 nodes;
151 u32 disable_siblings;
152 u32 cores_found;
153 int i, j;
154
155 /* get_nodes define in ht_wrapper.c */
156 nodes = get_nodes();
157
158 if (!CONFIG_LOGICAL_CPUS ||
159 read_option(multi_core, 0) != 0) { // 0 means multi core
160 disable_siblings = 1;
161 } else {
162 disable_siblings = 0;
163 }
164
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000165 for (i = 0; i < nodes; i++) {
Timothy Pearson0122afb2015-07-30 14:07:15 -0500166 if ((node >= 0) && (i != node))
167 continue;
168
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000169 cores_found = get_core_num_in_bsp(i);
170
171 u32 jstart, jend;
172
173 if (core_range == 2) {
174 jstart = 1;
175 } else {
176 jstart = 0;
177 }
178
179 if (disable_siblings || (core_range == 1)) {
180 jend = 0;
181 } else {
182 jend = cores_found;
183 }
184
185 for (j = jstart; j <= jend; j++) {
Timothy Pearson730a0432015-10-16 13:51:51 -0500186 ap_apicid = get_boot_apic_id(i, j);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000187
Patrick Georgif8f00622012-05-05 15:50:17 +0200188#if CONFIG_ENABLE_APIC_EXT_ID && (CONFIG_APIC_ID_OFFSET > 0)
Patrick Georgie1667822012-05-05 15:29:32 +0200189#if !CONFIG_LIFT_BSP_APIC_ID
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000190 if ((i != 0) || (j != 0)) /* except bsp */
191#endif
192 ap_apicid += CONFIG_APIC_ID_OFFSET;
193#endif
194
195 if (ap_apicid == bsp_apicid)
196 continue;
197
198 process_ap(ap_apicid, gp);
199
200 }
201 }
202}
203
204static inline int lapic_remote_read(int apicid, int reg, u32 *pvalue)
205{
206 int timeout;
207 u32 status;
208 int result;
209 lapic_wait_icr_idle();
210 lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
211 lapic_write(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4));
212
213/* Extra busy check compared to lapic.h */
214 timeout = 0;
215 do {
216 status = lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY;
217 } while (status == LAPIC_ICR_BUSY && timeout++ < 1000);
218
219 timeout = 0;
220 do {
221 status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK;
222 } while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000);
223
224 result = -1;
225
226 if (status == LAPIC_ICR_RR_VALID) {
227 *pvalue = lapic_read(LAPIC_RRR);
228 result = 0;
229 }
230 return result;
231}
232
Patrick Georgi76e81522010-11-16 21:25:29 +0000233#if CONFIG_SET_FIDVID
Xavi Drudis Ferran6bdc83b2011-02-28 03:56:52 +0000234static void init_fidvid_ap(u32 apicid, u32 nodeid, u32 coreid);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000235#endif
236
237static inline __attribute__ ((always_inline))
238void print_apicid_nodeid_coreid(u32 apicid, struct node_core_id id,
239 const char *str)
240{
241 printk(BIOS_DEBUG,
242 "%s --- { APICID = %02x NODEID = %02x COREID = %02x} ---\n", str,
243 apicid, id.nodeid, id.coreid);
244}
245
Timothy Pearson730a0432015-10-16 13:51:51 -0500246uint32_t wait_cpu_state(uint32_t apicid, uint32_t state, uint32_t state2)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000247{
248 u32 readback = 0;
249 u32 timeout = 1;
250 int loop = 4000000;
251 while (--loop > 0) {
252 if (lapic_remote_read(apicid, LAPIC_MSG_REG, &readback) != 0)
253 continue;
Timothy Pearson730a0432015-10-16 13:51:51 -0500254 if ((readback & 0x3f) == state || (readback & 0x3f) == state2 || (readback & 0x3f) == F10_APSTATE_RESET) {
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000255 timeout = 0;
256 break; //target cpu is in stage started
257 }
258 }
259 if (timeout) {
260 if (readback) {
261 timeout = readback;
262 }
263 }
264
265 return timeout;
266}
267
268static void wait_ap_started(u32 ap_apicid, void *gp)
269{
270 u32 timeout;
Timothy Pearson730a0432015-10-16 13:51:51 -0500271 timeout = wait_cpu_state(ap_apicid, F10_APSTATE_STARTED, F10_APSTATE_ASLEEP);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000272 printk(BIOS_DEBUG, "* AP %02x", ap_apicid);
273 if (timeout) {
274 printk(BIOS_DEBUG, " timed out:%08x\n", timeout);
275 } else {
276 printk(BIOS_DEBUG, "started\n");
277 }
278}
279
280void wait_all_other_cores_started(u32 bsp_apicid)
281{
282 // all aps other than core0
283 printk(BIOS_DEBUG, "started ap apicid: ");
Timothy Pearson0122afb2015-07-30 14:07:15 -0500284 for_each_ap(bsp_apicid, 2, -1, wait_ap_started, (void *)0);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000285 printk(BIOS_DEBUG, "\n");
286}
287
288void allow_all_aps_stop(u32 bsp_apicid)
289{
290 /* Called by the BSP to indicate AP can stop */
291
292 /* FIXME Do APs use this? */
293
294 // allow aps to stop use 6 bits for state
295 lapic_write(LAPIC_MSG_REG, (bsp_apicid << 24) | F10_APSTATE_STOPPED);
296}
297
298static void enable_apic_ext_id(u32 node)
299{
300 u32 val;
301
302 val = pci_read_config32(NODE_HT(node), 0x68);
303 val |= (HTTC_APIC_EXT_SPUR | HTTC_APIC_EXT_ID | HTTC_APIC_EXT_BRD_CST);
304 pci_write_config32(NODE_HT(node), 0x68, val);
305}
306
Timothy Pearson730a0432015-10-16 13:51:51 -0500307static void STOP_CAR_AND_CPU(uint8_t skip_sharedc_config, uint32_t apicid)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000308{
309 msr_t msr;
Timothy Pearson730a0432015-10-16 13:51:51 -0500310 uint32_t family;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000311
Timothy Pearson730a0432015-10-16 13:51:51 -0500312 family = amd_fam1x_cpu_family(); // inline
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000313
Timothy Pearson730a0432015-10-16 13:51:51 -0500314 if (family < 0x6f) {
315 /* Family 10h or earlier */
316
317 /* Disable L2 IC to L3 connection (Only for CAR) */
318 msr = rdmsr(BU_CFG2);
319 msr.lo &= ~(1 << ClLinesToNbDis);
320 wrmsr(BU_CFG2, msr);
Timothy Pearson38508a02015-06-25 15:07:34 -0500321 } else {
322 /* Family 15h or later
323 * DRAM setup is delayed on Fam15 in order to prevent
324 * any DRAM access before ECC check bits are initialized.
325 * Each core also needs to have its initial DRAM map initialized
326 * before it is put to sleep, otherwise it will fail to wake
327 * in ramstage. To meet both of these goals, delay DRAM map
328 * setup until the last possible moment, where speculative
329 * memory access is highly unlikely before core halt...
330 */
331 if (!skip_sharedc_config) {
332 /* Enable memory access for first MBs using top_mem */
333 msr.hi = 0;
334 msr.lo = (CONFIG_RAMTOP + TOP_MEM_MASK) & (~TOP_MEM_MASK);
335 wrmsr(TOP_MEM, msr);
336 }
Timothy Pearson730a0432015-10-16 13:51:51 -0500337 }
338
339 disable_cache_as_ram(skip_sharedc_config); // inline
340
341 /* Mark the core as sleeping */
342 lapic_write(LAPIC_MSG_REG, (apicid << 24) | F10_APSTATE_ASLEEP);
343
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000344 /* stop all cores except node0/core0 the bsp .... */
345 stop_this_cpu();
346}
347
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000348static u32 init_cpus(u32 cpu_init_detectedx, struct sys_info *sysinfo)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000349{
Timothy Pearson0f1553b2015-08-02 21:06:39 -0500350 uint32_t bsp_apicid = 0;
351 uint32_t apicid;
352 uint32_t dword;
Timothy Pearson730a0432015-10-16 13:51:51 -0500353 uint8_t set_mtrrs;
Timothy Pearson0f1553b2015-08-02 21:06:39 -0500354 uint8_t node_count;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000355 struct node_core_id id;
356
Timothy Pearsonfb39f822015-06-02 20:25:03 -0500357 /* Please refer to the calculations and explaination in cache_as_ram.inc before modifying these values */
Timothy Pearsonb5e46552015-06-02 13:47:36 -0500358 uint32_t max_ap_stack_region_size = CONFIG_MAX_CPUS * CONFIG_DCACHE_AP_STACK_SIZE;
Timothy Pearsonfb39f822015-06-02 20:25:03 -0500359 uint32_t max_bsp_stack_region_size = CONFIG_DCACHE_BSP_STACK_SIZE + CONFIG_DCACHE_BSP_STACK_SLUSH;
360 uint32_t bsp_stack_region_upper_boundary = CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE;
361 uint32_t bsp_stack_region_lower_boundary = bsp_stack_region_upper_boundary - max_bsp_stack_region_size;
Timothy Pearsonb5e46552015-06-02 13:47:36 -0500362 void * lower_stack_region_boundary = (void*)(bsp_stack_region_lower_boundary - max_ap_stack_region_size);
363 if (((void*)(sysinfo + 1)) > lower_stack_region_boundary)
364 printk(BIOS_WARNING,
365 "sysinfo extends into stack region (sysinfo range: [%p,%p] lower stack region boundary: %p)\n",
366 sysinfo, sysinfo + 1, lower_stack_region_boundary);
367
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000368 /*
369 * already set early mtrr in cache_as_ram.inc
370 */
371
372 /* that is from initial apicid, we need nodeid and coreid
373 later */
374 id = get_node_core_id_x();
375
376 /* NB_CFG MSR is shared between cores, so we need make sure
377 core0 is done at first --- use wait_all_core0_started */
378 if (id.coreid == 0) {
Timothy Pearson0122afb2015-07-30 14:07:15 -0500379 /* Set InitApicIdCpuIdLo / EnableCf8ExtCfg on core0 only */
380 if (!is_fam15h())
381 set_apicid_cpuid_lo();
382 set_EnableCf8ExtCfg();
Patrick Georgie1667822012-05-05 15:29:32 +0200383#if CONFIG_ENABLE_APIC_EXT_ID
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000384 enable_apic_ext_id(id.nodeid);
385#endif
386 }
387
388 enable_lapic();
389
Patrick Georgif8f00622012-05-05 15:50:17 +0200390#if CONFIG_ENABLE_APIC_EXT_ID && (CONFIG_APIC_ID_OFFSET > 0)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000391 u32 initial_apicid = get_initial_apicid();
392
Patrick Georgie1667822012-05-05 15:29:32 +0200393#if !CONFIG_LIFT_BSP_APIC_ID
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000394 if (initial_apicid != 0) // other than bsp
395#endif
396 {
397 /* use initial apic id to lift it */
398 u32 dword = lapic_read(LAPIC_ID);
399 dword &= ~(0xff << 24);
400 dword |=
401 (((initial_apicid + CONFIG_APIC_ID_OFFSET) & 0xff) << 24);
402
403 lapic_write(LAPIC_ID, dword);
404 }
Patrick Georgie1667822012-05-05 15:29:32 +0200405#if CONFIG_LIFT_BSP_APIC_ID
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000406 bsp_apicid += CONFIG_APIC_ID_OFFSET;
407#endif
408
409#endif
410
411 /* get the apicid, it may be lifted already */
412 apicid = lapicid();
413
414 // show our apicid, nodeid, and coreid
415 if (id.coreid == 0) {
416 if (id.nodeid != 0) //all core0 except bsp
417 print_apicid_nodeid_coreid(apicid, id, " core0: ");
418 } else { //all other cores
419 print_apicid_nodeid_coreid(apicid, id, " corex: ");
420 }
421
422 if (cpu_init_detectedx) {
423 print_apicid_nodeid_coreid(apicid, id,
424 "\n\n\nINIT detected from ");
425 printk(BIOS_DEBUG, "\nIssuing SOFT_RESET...\n");
426 soft_reset();
427 }
428
429 if (id.coreid == 0) {
430 if (!(warm_reset_detect(id.nodeid))) //FIXME: INIT is checked above but check for more resets?
431 distinguish_cpu_resets(id.nodeid); // Also indicates we are started
432 }
433 // Mark the core as started.
434 lapic_write(LAPIC_MSG_REG, (apicid << 24) | F10_APSTATE_STARTED);
Timothy Pearson0122afb2015-07-30 14:07:15 -0500435 printk(BIOS_DEBUG, "CPU APICID %02x start flag set\n", apicid);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000436
437 if (apicid != bsp_apicid) {
438 /* Setup each AP's cores MSRs.
439 * This happens after HTinit.
440 * The BSP runs this code in it's own path.
441 */
442 update_microcode(cpuid_eax(1));
Kyösti Mälkkif0a13ce2013-12-08 07:20:48 +0200443
Timothy Pearson730a0432015-10-16 13:51:51 -0500444 cpuSetAMDMSR(id.nodeid);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000445
Timothy Pearson0f1553b2015-08-02 21:06:39 -0500446 /* Set up HyperTransport probe filter support */
447 if (is_gt_rev_d()) {
448 dword = pci_read_config32(NODE_PCI(id.nodeid, 0), 0x60);
449 node_count = ((dword >> 4) & 0x7) + 1;
450
451 if (node_count > 1) {
452 msr_t msr = rdmsr(BU_CFG2_MSR);
453 msr.hi |= 1 << (42 - 32);
454 wrmsr(BU_CFG2_MSR, msr);
455 }
456 }
457
Patrick Georgi76e81522010-11-16 21:25:29 +0000458#if CONFIG_SET_FIDVID
Patrick Georgif8f00622012-05-05 15:50:17 +0200459#if CONFIG_LOGICAL_CPUS && CONFIG_SET_FIDVID_CORE0_ONLY
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000460 // Run on all AP for proper FID/VID setup.
461 if (id.coreid == 0) // only need set fid for core0
462#endif
463 {
464 // check warm(bios) reset to call stage2 otherwise do stage1
465 if (warm_reset_detect(id.nodeid)) {
466 printk(BIOS_DEBUG,
467 "init_fidvid_stage2 apicid: %02x\n",
468 apicid);
469 init_fidvid_stage2(apicid, id.nodeid);
470 } else {
471 printk(BIOS_DEBUG,
472 "init_fidvid_ap(stage1) apicid: %02x\n",
473 apicid);
Xavi Drudis Ferran6bdc83b2011-02-28 03:56:52 +0000474 init_fidvid_ap(apicid, id.nodeid, id.coreid);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000475 }
476 }
477#endif
478
Timothy Pearson730a0432015-10-16 13:51:51 -0500479 if (is_fam15h()) {
480 /* core 1 on node 0 is special; to avoid corrupting the
481 * BSP do not alter MTRRs on that core */
482 if (apicid == 1)
483 set_mtrrs = 0;
484 else
485 set_mtrrs = !!(apicid & 0x1);
486 } else {
487 set_mtrrs = 1;
488 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000489
Timothy Pearson730a0432015-10-16 13:51:51 -0500490 /* AP is ready, configure MTRRs and go to sleep */
491 if (set_mtrrs)
492 set_var_mtrr(0, 0x00000000, CONFIG_RAMTOP, MTRR_TYPE_WRBACK);
493
494 printk(BIOS_DEBUG, "Disabling CAR on AP %02x\n", apicid);
495 if (is_fam15h()) {
496 /* Only modify the MSRs on the odd cores (the last cores to finish booting) */
497 STOP_CAR_AND_CPU(!set_mtrrs, apicid);
498 } else {
499 /* Modify MSRs on all cores */
500 STOP_CAR_AND_CPU(0, apicid);
501 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000502
503 printk(BIOS_DEBUG,
504 "\nAP %02x should be halted but you are reading this....\n",
505 apicid);
506 }
507
508 return bsp_apicid;
509}
510
511static u32 is_core0_started(u32 nodeid)
512{
513 u32 htic;
514 device_t device;
515 device = NODE_PCI(nodeid, 0);
516 htic = pci_read_config32(device, HT_INIT_CONTROL);
517 htic &= HTIC_ColdR_Detect;
518 return htic;
519}
520
521void wait_all_core0_started(void)
522{
523 /* When core0 is started, it will distingush_cpu_resets
524 * So wait for that to finish */
525 u32 i;
526 u32 nodes = get_nodes();
527
528 printk(BIOS_DEBUG, "core0 started: ");
529 for (i = 1; i < nodes; i++) { // skip bsp, because it is running on bsp
530 while (!is_core0_started(i)) {
531 }
532 printk(BIOS_DEBUG, " %02x", i);
533 }
534 printk(BIOS_DEBUG, "\n");
535}
536
537#if CONFIG_MAX_PHYSICAL_CPUS > 1
538/**
539 * void start_node(u32 node)
540 *
541 * start the core0 in node, so it can generate HT packet to feature code.
542 *
543 * This function starts the AP nodes core0s. wait_all_core0_started() in
544 * romstage.c waits for all the AP to be finished before continuing
545 * system init.
546 */
547static void start_node(u8 node)
548{
549 u32 val;
550
551 /* Enable routing table */
552 printk(BIOS_DEBUG, "Start node %02x", node);
553
554#if CONFIG_NORTHBRIDGE_AMD_AMDFAM10
555 /* For FAM10 support, we need to set Dram base/limit for the new node */
556 pci_write_config32(NODE_MP(node), 0x44, 0);
557 pci_write_config32(NODE_MP(node), 0x40, 3);
558#endif
559
560 /* Allow APs to make requests (ROM fetch) */
561 val = pci_read_config32(NODE_HT(node), 0x6c);
562 val &= ~(1 << 1);
563 pci_write_config32(NODE_HT(node), 0x6c, val);
564
565 printk(BIOS_DEBUG, " done.\n");
566}
567
568/**
569 * static void setup_remote_node(u32 node)
570 *
Martin Roth4c3ab732013-07-08 16:23:54 -0600571 * Copy the BSP Address Map to each AP.
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000572 */
573static void setup_remote_node(u8 node)
574{
575 /* There registers can be used with F1x114_x Address Map at the
576 same time, So must set them even 32 node */
577 static const u16 pci_reg[] = {
578 /* DRAM Base/Limits Registers */
579 0x44, 0x4c, 0x54, 0x5c, 0x64, 0x6c, 0x74, 0x7c,
580 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78,
581 0x144, 0x14c, 0x154, 0x15c, 0x164, 0x16c, 0x174, 0x17c,
582 0x140, 0x148, 0x150, 0x158, 0x160, 0x168, 0x170, 0x178,
583 /* MMIO Base/Limits Registers */
584 0x84, 0x8c, 0x94, 0x9c, 0xa4, 0xac, 0xb4, 0xbc,
585 0x80, 0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8,
586 /* IO Base/Limits Registers */
587 0xc4, 0xcc, 0xd4, 0xdc,
588 0xc0, 0xc8, 0xd0, 0xd8,
589 /* Configuration Map Registers */
590 0xe0, 0xe4, 0xe8, 0xec,
591 };
592 u16 i;
593
594 printk(BIOS_DEBUG, "setup_remote_node: %02x", node);
595
596 /* copy the default resource map from node 0 */
597 for (i = 0; i < ARRAY_SIZE(pci_reg); i++) {
598 u32 value;
599 u16 reg;
600 reg = pci_reg[i];
601 value = pci_read_config32(NODE_MP(0), reg);
602 pci_write_config32(NODE_MP(node), reg, value);
603
604 }
605 printk(BIOS_DEBUG, " done\n");
606}
607#endif /* CONFIG_MAX_PHYSICAL_CPUS > 1 */
608
Timothy Pearson0122afb2015-07-30 14:07:15 -0500609//it is running on core0 of node0
610static void start_other_cores(uint32_t bsp_apicid)
611{
612 u32 nodes;
613 u32 nodeid;
614
615 // disable multi_core
616 if (read_option(multi_core, 0) != 0) {
617 printk(BIOS_DEBUG, "Skip additional core init\n");
618 return;
619 }
620
621 nodes = get_nodes();
622
623 for (nodeid = 0; nodeid < nodes; nodeid++) {
624 u32 cores = get_core_num_in_bsp(nodeid);
625 printk(BIOS_DEBUG, "init node: %02x cores: %02x pass 1\n", nodeid, cores);
626 if (cores > 0) {
627 real_start_other_core(nodeid, cores);
628#ifdef FAM10_AP_NODE_SEQUENTIAL_START
629 printk(BIOS_DEBUG, "waiting for core start on node %d...\n", nodeid);
630 for_each_ap(bsp_apicid, 2, nodeid, wait_ap_started, (void *)0);
631 printk(BIOS_DEBUG, "...started\n");
632#endif
633 }
634 }
635}
636
Timothy Pearson730a0432015-10-16 13:51:51 -0500637static void AMD_Errata281(u8 node, uint64_t revision, u32 platform)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000638{
639 /* Workaround for Transaction Scheduling Conflict in
640 * Northbridge Cross Bar. Implement XCS Token adjustment
641 * for ganged links. Also, perform fix up for the mixed
642 * revision case.
643 */
644
645 u32 reg, val;
646 u8 i;
647 u8 mixed = 0;
648 u8 nodes = get_nodes();
649
650 if (platform & AMD_PTYPE_SVR) {
651 /* For each node we need to check for a "broken" node */
652 if (!(revision & (AMD_DR_B0 | AMD_DR_B1))) {
653 for (i = 0; i < nodes; i++) {
654 if (mctGetLogicalCPUID(i) &
655 (AMD_DR_B0 | AMD_DR_B1)) {
656 mixed = 1;
657 break;
658 }
659 }
660 }
661
662 if ((revision & (AMD_DR_B0 | AMD_DR_B1)) || mixed) {
663
664 /* F0X68[22:21] DsNpReqLmt0 = 01b */
665 val = pci_read_config32(NODE_PCI(node, 0), 0x68);
666 val &= ~0x00600000;
667 val |= 0x00200000;
668 pci_write_config32(NODE_PCI(node, 0), 0x68, val);
669
670 /* F3X6C */
671 val = pci_read_config32(NODE_PCI(node, 3), 0x6C);
672 val &= ~0x700780F7;
673 val |= 0x00010094;
674 pci_write_config32(NODE_PCI(node, 3), 0x6C, val);
675
676 /* F3X7C */
677 val = pci_read_config32(NODE_PCI(node, 3), 0x7C);
678 val &= ~0x707FFF1F;
679 val |= 0x00144514;
680 pci_write_config32(NODE_PCI(node, 3), 0x7C, val);
681
682 /* F3X144[3:0] RspTok = 0001b */
683 val = pci_read_config32(NODE_PCI(node, 3), 0x144);
684 val &= ~0x0000000F;
685 val |= 0x00000001;
686 pci_write_config32(NODE_PCI(node, 3), 0x144, val);
687
688 for (i = 0; i < 3; i++) {
689 reg = 0x148 + (i * 4);
690 val = pci_read_config32(NODE_PCI(node, 3), reg);
691 val &= ~0x000000FF;
692 val |= 0x000000DB;
693 pci_write_config32(NODE_PCI(node, 3), reg, val);
694 }
695 }
696 }
697}
698
699static void AMD_Errata298(void)
700{
701 /* Workaround for L2 Eviction May Occur during operation to
702 * set Accessed or dirty bit.
703 */
704
705 msr_t msr;
706 u8 i;
707 u8 affectedRev = 0;
708 u8 nodes = get_nodes();
709
710 /* For each core we need to check for a "broken" node */
711 for (i = 0; i < nodes; i++) {
712 if (mctGetLogicalCPUID(i) & (AMD_DR_B0 | AMD_DR_B1 | AMD_DR_B2)) {
713 affectedRev = 1;
714 break;
715 }
716 }
717
718 if (affectedRev) {
719 msr = rdmsr(HWCR);
720 msr.lo |= 0x08; /* Set TlbCacheDis bit[3] */
721 wrmsr(HWCR, msr);
722
723 msr = rdmsr(BU_CFG);
724 msr.lo |= 0x02; /* Set TlbForceMemTypeUc bit[1] */
725 wrmsr(BU_CFG, msr);
726
727 msr = rdmsr(OSVW_ID_Length);
728 msr.lo |= 0x01; /* OS Visible Workaround - MSR */
729 wrmsr(OSVW_ID_Length, msr);
730
731 msr = rdmsr(OSVW_Status);
732 msr.lo |= 0x01; /* OS Visible Workaround - MSR */
733 wrmsr(OSVW_Status, msr);
734 }
735
736 if (!affectedRev && (mctGetLogicalCPUID(0xFF) & AMD_DR_B3)) {
737 msr = rdmsr(OSVW_ID_Length);
738 msr.lo |= 0x01; /* OS Visible Workaround - MSR */
739 wrmsr(OSVW_ID_Length, msr);
740
741 }
742}
743
744static u32 get_platform_type(void)
745{
746 u32 ret = 0;
747
748 switch (SYSTEM_TYPE) {
749 case 1:
750 ret |= AMD_PTYPE_DSK;
751 break;
752 case 2:
753 ret |= AMD_PTYPE_MOB;
754 break;
755 case 0:
756 ret |= AMD_PTYPE_SVR;
757 break;
758 default:
759 break;
760 }
761
762 /* FIXME: add UMA support. */
763
764 /* All Fam10 are multi core */
765 ret |= AMD_PTYPE_MC;
766
767 return ret;
768}
769
770static void AMD_SetupPSIVID_d(u32 platform_type, u8 node)
771{
772 u32 dword;
773 int i;
774 msr_t msr;
775
776 if (platform_type & (AMD_PTYPE_MOB | AMD_PTYPE_DSK)) {
777
778 /* The following code sets the PSIVID to the lowest support P state
779 * assuming that the VID for the lowest power state is below
780 * the VDD voltage regulator threshold. (This also assumes that there
781 * is a Pstate lower than P0)
782 */
783
784 for (i = 4; i >= 0; i--) {
785 msr = rdmsr(PS_REG_BASE + i);
786 /* Pstate valid? */
787 if (msr.hi & PS_EN_MASK) {
788 dword = pci_read_config32(NODE_PCI(i, 3), 0xA0);
789 dword &= ~0x7F;
790 dword |= (msr.lo >> 9) & 0x7F;
791 pci_write_config32(NODE_PCI(i, 3), 0xA0, dword);
792 break;
793 }
794 }
795 }
796}
797
798/**
799 * AMD_CpuFindCapability - Traverse PCI capability list to find host HT links.
800 * HT Phy operations are not valid on links that aren't present, so this
801 * prevents invalid accesses.
802 *
803 * Returns the offset of the link register.
804 */
805static BOOL AMD_CpuFindCapability(u8 node, u8 cap_count, u8 * offset)
806{
807 u32 reg;
808 u32 val;
809
810 /* get start of CPU HT Host Capabilities */
811 val = pci_read_config32(NODE_PCI(node, 0), 0x34);
812 val &= 0xFF; //reg offset of first link
813
814 cap_count++;
815
816 /* Traverse through the capabilities. */
817 do {
818 reg = pci_read_config32(NODE_PCI(node, 0), val);
819 /* Is the capability block a HyperTransport capability block? */
820 if ((reg & 0xFF) == 0x08) {
821 /* Is the HT capability block an HT Host Capability? */
822 if ((reg & 0xE0000000) == (1 << 29))
823 cap_count--;
824 }
825
826 if (cap_count)
827 val = (reg >> 8) & 0xFF; //update reg offset
828 } while (cap_count && val);
829
830 *offset = (u8) val;
831
832 /* If requested capability found val != 0 */
833 if (!cap_count)
834 return TRUE;
835 else
836 return FALSE;
837}
838
839/**
840 * AMD_checkLinkType - Compare desired link characteristics using a logical
841 * link type mask.
842 *
843 * Returns the link characteristic mask.
844 */
Timothy Pearsonf8549e82015-09-07 22:26:55 -0500845static u32 AMD_checkLinkType(u8 node, u8 regoff)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000846{
Timothy Pearson965704a2015-08-07 19:04:49 -0500847 uint32_t val;
848 uint32_t val2;
849 uint32_t linktype = 0;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000850
851 /* Check connect, init and coherency */
852 val = pci_read_config32(NODE_PCI(node, 0), regoff + 0x18);
853 val &= 0x1F;
854
855 if (val == 3)
856 linktype |= HTPHY_LINKTYPE_COHERENT;
857
858 if (val == 7)
859 linktype |= HTPHY_LINKTYPE_NONCOHERENT;
860
861 if (linktype) {
862 /* Check gen3 */
863 val = pci_read_config32(NODE_PCI(node, 0), regoff + 0x08);
Timothy Pearson965704a2015-08-07 19:04:49 -0500864 val = (val >> 8) & 0xf;
865 if (is_gt_rev_d()) {
866 val2 = pci_read_config32(NODE_PCI(node, 0), regoff + 0x1c);
867 val |= (val2 & 0x1) << 4;
868 }
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000869
Timothy Pearson965704a2015-08-07 19:04:49 -0500870 if (val > 6)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000871 linktype |= HTPHY_LINKTYPE_HT3;
872 else
873 linktype |= HTPHY_LINKTYPE_HT1;
874
875 /* Check ganged */
Timothy Pearsonf8549e82015-09-07 22:26:55 -0500876 val = pci_read_config32(NODE_PCI(node, 0), (((regoff - 0x80) / 0x20) << 2) + 0x170);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000877
878 if (val & 1)
879 linktype |= HTPHY_LINKTYPE_GANGED;
880 else
881 linktype |= HTPHY_LINKTYPE_UNGANGED;
882 }
Timothy Pearsone536a4d2015-08-02 21:31:17 -0500883
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000884 return linktype;
885}
886
887/**
888 * AMD_SetHtPhyRegister - Use the HT link's HT Phy portal registers to update
889 * a phy setting for that link.
890 */
891static void AMD_SetHtPhyRegister(u8 node, u8 link, u8 entry)
892{
893 u32 phyReg;
894 u32 phyBase;
895 u32 val;
896
897 /* Determine this link's portal */
898 if (link > 3)
899 link -= 4;
900
901 phyBase = ((u32) link << 3) | 0x180;
902
Timothy Pearson0122afb2015-07-30 14:07:15 -0500903 /* Determine if link is connected and abort if not */
904 if (!(pci_read_config32(NODE_PCI(node, 0), 0x98 + (link * 0x20)) & 0x1))
905 return;
906
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000907 /* Get the portal control register's initial value
908 * and update it to access the desired phy register
909 */
910 phyReg = pci_read_config32(NODE_PCI(node, 4), phyBase);
911
912 if (fam10_htphy_default[entry].htreg > 0x1FF) {
913 phyReg &= ~HTPHY_DIRECT_OFFSET_MASK;
914 phyReg |= HTPHY_DIRECT_MAP;
915 } else {
916 phyReg &= ~HTPHY_OFFSET_MASK;
917 }
918
919 /* Now get the current phy register data
920 * LinkPhyDone = 0, LinkPhyWrite = 0 is a read
921 */
922 phyReg |= fam10_htphy_default[entry].htreg;
923 pci_write_config32(NODE_PCI(node, 4), phyBase, phyReg);
924
925 do {
926 val = pci_read_config32(NODE_PCI(node, 4), phyBase);
927 } while (!(val & HTPHY_IS_COMPLETE_MASK));
928
929 /* Now we have the phy register data, apply the change */
930 val = pci_read_config32(NODE_PCI(node, 4), phyBase + 4);
931 val &= ~fam10_htphy_default[entry].mask;
932 val |= fam10_htphy_default[entry].data;
933 pci_write_config32(NODE_PCI(node, 4), phyBase + 4, val);
934
935 /* write it through the portal to the phy
936 * LinkPhyDone = 0, LinkPhyWrite = 1 is a write
937 */
938 phyReg |= HTPHY_WRITE_CMD;
939 pci_write_config32(NODE_PCI(node, 4), phyBase, phyReg);
940
941 do {
942 val = pci_read_config32(NODE_PCI(node, 4), phyBase);
943 } while (!(val & HTPHY_IS_COMPLETE_MASK));
944}
945
Timothy Pearson730a0432015-10-16 13:51:51 -0500946void cpuSetAMDMSR(uint8_t node_id)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000947{
948 /* This routine loads the CPU with default settings in fam10_msr_default
949 * table . It must be run after Cache-As-RAM has been enabled, and
950 * Hypertransport initialization has taken place. Also note
951 * that it is run on the current processor only, and only for the current
952 * processor core.
953 */
954 msr_t msr;
955 u8 i;
Timothy Pearson68130f52015-08-09 02:47:51 -0500956 uint8_t nvram;
Timothy Pearson730a0432015-10-16 13:51:51 -0500957 u32 platform;
958 uint64_t revision;
Timothy Pearson83abd812015-06-08 19:35:06 -0500959 uint8_t enable_c_states;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +0000960
961 printk(BIOS_DEBUG, "cpuSetAMDMSR ");
962
963 revision = mctGetLogicalCPUID(0xFF);
964 platform = get_platform_type();
965
966 for (i = 0; i < ARRAY_SIZE(fam10_msr_default); i++) {
967 if ((fam10_msr_default[i].revision & revision) &&
968 (fam10_msr_default[i].platform & platform)) {
969 msr = rdmsr(fam10_msr_default[i].msr);
970 msr.hi &= ~fam10_msr_default[i].mask_hi;
971 msr.hi |= fam10_msr_default[i].data_hi;
972 msr.lo &= ~fam10_msr_default[i].mask_lo;
973 msr.lo |= fam10_msr_default[i].data_lo;
974 wrmsr(fam10_msr_default[i].msr, msr);
975 }
976 }
977 AMD_Errata298();
978
Timothy Pearson730a0432015-10-16 13:51:51 -0500979 /* Revision C0 and above */
980 if (revision & AMD_OR_C0) {
Timothy Pearson68130f52015-08-09 02:47:51 -0500981 uint8_t enable_experimental_memory_speed_boost;
982
983 /* Check to see if cache partitioning is allowed */
984 enable_experimental_memory_speed_boost = 0;
985 if (get_option(&nvram, "experimental_memory_speed_boost") == CB_SUCCESS)
986 enable_experimental_memory_speed_boost = !!nvram;
987
Timothy Pearson730a0432015-10-16 13:51:51 -0500988 uint32_t f3x1fc = pci_read_config32(NODE_PCI(node_id, 3), 0x1fc);
989 msr = rdmsr(FP_CFG);
990 msr.hi &= ~(0x7 << (42-32)); /* DiDtCfg4 */
991 msr.hi |= (((f3x1fc >> 17) & 0x7) << (42-32));
992 msr.hi &= ~(0x1 << (41-32)); /* DiDtCfg5 */
993 msr.hi |= (((f3x1fc >> 22) & 0x1) << (41-32));
994 msr.hi &= ~(0x1 << (40-32)); /* DiDtCfg3 */
995 msr.hi |= (((f3x1fc >> 16) & 0x1) << (40-32));
996 msr.hi &= ~(0x7 << (32-32)); /* DiDtCfg1 (1) */
997 msr.hi |= (((f3x1fc >> 11) & 0x7) << (32-32));
998 msr.lo &= ~(0x1f << 27); /* DiDtCfg1 (2) */
999 msr.lo |= (((f3x1fc >> 6) & 0x1f) << 27);
1000 msr.lo &= ~(0x3 << 25); /* DiDtCfg2 */
1001 msr.lo |= (((f3x1fc >> 14) & 0x3) << 25);
1002 msr.lo &= ~(0x1f << 18); /* DiDtCfg0 */
1003 msr.lo |= (((f3x1fc >> 1) & 0x1f) << 18);
1004 msr.lo &= ~(0x1 << 16); /* DiDtMode */
1005 msr.lo |= ((f3x1fc & 0x1) << 16);
1006 wrmsr(FP_CFG, msr);
Timothy Pearson68130f52015-08-09 02:47:51 -05001007
1008 if (enable_experimental_memory_speed_boost) {
1009 msr = rdmsr(BU_CFG3);
1010 msr.lo |= (0x3 << 20); /* PfcStrideMul = 0x3 */
1011 wrmsr(BU_CFG3, msr);
1012 }
Timothy Pearson730a0432015-10-16 13:51:51 -05001013 }
1014
Timothy Pearson83abd812015-06-08 19:35:06 -05001015#if IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB700) || IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB800)
Timothy Pearson83abd812015-06-08 19:35:06 -05001016 if (revision & (AMD_DR_GT_D0 | AMD_FAM15_ALL)) {
1017 /* Set up message triggered C1E */
1018 msr = rdmsr(0xc0010055);
1019 msr.lo &= ~0xffff; /* IOMsgAddr = ACPI_PM_EVT_BLK */
1020 msr.lo |= ACPI_PM_EVT_BLK & 0xffff;
1021 msr.lo |= (0x1 << 29); /* BmStsClrOnHltEn = 1 */
1022 if (revision & AMD_DR_GT_D0) {
1023 msr.lo &= ~(0x1 << 28); /* C1eOnCmpHalt = 0 */
1024 msr.lo &= ~(0x1 << 27); /* SmiOnCmpHalt = 0 */
1025 }
1026 wrmsr(0xc0010055, msr);
1027
1028 msr = rdmsr(0xc0010015);
1029 msr.lo |= (0x1 << 12); /* HltXSpCycEn = 1 */
1030 wrmsr(0xc0010015, msr);
1031 }
1032
1033 if (revision & (AMD_DR_Ex | AMD_FAM15_ALL)) {
1034 enable_c_states = 0;
1035 if (IS_ENABLED(CONFIG_HAVE_ACPI_TABLES))
1036 if (get_option(&nvram, "cpu_c_states") == CB_SUCCESS)
1037 enable_c_states = !!nvram;
1038
1039 if (enable_c_states) {
1040 /* Set up the C-state base address */
1041 msr_t c_state_addr_msr;
1042 c_state_addr_msr = rdmsr(0xc0010073);
1043 c_state_addr_msr.lo = ACPI_CPU_P_LVL2; /* CstateAddr = ACPI_CPU_P_LVL2 */
1044 wrmsr(0xc0010073, c_state_addr_msr);
1045 }
1046 }
1047#else
1048 enable_c_states = 0;
1049#endif
1050
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001051 printk(BIOS_DEBUG, " done\n");
1052}
1053
1054static void cpuSetAMDPCI(u8 node)
1055{
1056 /* This routine loads the CPU with default settings in fam10_pci_default
1057 * table . It must be run after Cache-As-RAM has been enabled, and
1058 * Hypertransport initialization has taken place. Also note
1059 * that it is run for the first core on each node
1060 */
Timothy Pearson0122afb2015-07-30 14:07:15 -05001061 uint8_t i;
1062 uint8_t j;
Timothy Pearson730a0432015-10-16 13:51:51 -05001063 u32 platform;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001064 u32 val;
Timothy Pearson0122afb2015-07-30 14:07:15 -05001065 uint8_t offset;
Timothy Pearson83abd812015-06-08 19:35:06 -05001066 uint32_t dword;
Timothy Pearson730a0432015-10-16 13:51:51 -05001067 uint64_t revision;
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001068
Timothy Pearson71b8f012015-08-07 23:59:17 -05001069 /* FIXME
1070 * This should be configurable
1071 */
1072 uint8_t sockets = 2;
1073 uint8_t sockets_populated = 2;
1074
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001075 printk(BIOS_DEBUG, "cpuSetAMDPCI %02d", node);
1076
1077 revision = mctGetLogicalCPUID(node);
1078 platform = get_platform_type();
1079
1080 AMD_SetupPSIVID_d(platform, node); /* Set PSIVID offset which is not table driven */
1081
1082 for (i = 0; i < ARRAY_SIZE(fam10_pci_default); i++) {
1083 if ((fam10_pci_default[i].revision & revision) &&
1084 (fam10_pci_default[i].platform & platform)) {
1085 val = pci_read_config32(NODE_PCI(node,
1086 fam10_pci_default[i].
1087 function),
1088 fam10_pci_default[i].offset);
1089 val &= ~fam10_pci_default[i].mask;
1090 val |= fam10_pci_default[i].data;
1091 pci_write_config32(NODE_PCI(node,
1092 fam10_pci_default[i].
1093 function),
1094 fam10_pci_default[i].offset, val);
1095 }
1096 }
1097
Timothy Pearson0122afb2015-07-30 14:07:15 -05001098#ifdef DEBUG_HT_SETUP
1099 /* Dump link settings */
1100 for (i = 0; i < 4; i++) {
1101 for (j = 0; j < 4; j++) {
1102 printk(BIOS_DEBUG, "Node %d link %d: type register: %08x control register: %08x extended control sublink 0: %08x 1: %08x\n", i, j,
1103 pci_read_config32(NODE_PCI(i, 0), 0x98 + (j * 0x20)), pci_read_config32(NODE_PCI(i, 0), 0x84 + (j * 0x20)),
1104 pci_read_config32(NODE_PCI(i, 0), 0x170 + (j * 0x4)), pci_read_config32(NODE_PCI(i, 0), 0x180 + (j * 0x4)));
1105 }
1106 }
1107#endif
1108
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001109 for (i = 0; i < ARRAY_SIZE(fam10_htphy_default); i++) {
1110 if ((fam10_htphy_default[i].revision & revision) &&
1111 (fam10_htphy_default[i].platform & platform)) {
1112 /* HT Phy settings either apply to both sublinks or have
1113 * separate registers for sublink zero and one, so there
1114 * will be two table entries. So, here we only loop
1115 * through the sublink zeros in function zero.
1116 */
1117 for (j = 0; j < 4; j++) {
1118 if (AMD_CpuFindCapability(node, j, &offset)) {
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001119 if (AMD_checkLinkType(node, offset)
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001120 & fam10_htphy_default[i].linktype) {
1121 AMD_SetHtPhyRegister(node, j,
1122 i);
1123 }
1124 } else {
1125 /* No more capabilities,
1126 * link not present
1127 */
1128 break;
1129 }
1130 }
1131 }
1132 }
1133
1134 /* FIXME: add UMA support and programXbarToSriReg(); */
1135
1136 AMD_Errata281(node, revision, platform);
1137
1138 /* FIXME: if the dct phy doesn't init correct it needs to reset.
1139 if (revision & (AMD_DR_B2 | AMD_DR_B3))
1140 dctPhyDiag(); */
1141
Timothy Pearson83abd812015-06-08 19:35:06 -05001142 if (revision & (AMD_DR_GT_D0 | AMD_FAM15_ALL)) {
1143 /* Set up message triggered C1E */
1144 dword = pci_read_config32(NODE_PCI(node, 3), 0xd4);
1145 dword &= ~(0x1 << 14); /* CacheFlushImmOnAllHalt = !is_fam15h() */
1146 dword |= (is_fam15h()?0:1) << 14;
1147 pci_write_config32(NODE_PCI(node, 3), 0xd4, dword);
1148
1149 dword = pci_read_config32(NODE_PCI(node, 3), 0xdc);
1150 dword |= 0x1 << 26; /* IgnCpuPrbEn = 1 */
1151 dword &= ~(0x7f << 19); /* CacheFlushOnHaltTmr = 0x28 */
1152 dword |= 0x28 << 19;
1153 dword |= 0x7 << 16; /* CacheFlushOnHaltCtl = 0x7 */
1154 pci_write_config32(NODE_PCI(node, 3), 0xdc, dword);
1155
1156 dword = pci_read_config32(NODE_PCI(node, 3), 0xa0);
1157 dword |= 0x1 << 10; /* IdleExitEn = 1 */
1158 pci_write_config32(NODE_PCI(node, 3), 0xa0, dword);
1159
1160 if (revision & AMD_DR_GT_D0) {
1161 dword = pci_read_config32(NODE_PCI(node, 3), 0x188);
1162 dword |= 0x1 << 4; /* EnStpGntOnFlushMaskWakeup = 1 */
1163 pci_write_config32(NODE_PCI(node, 3), 0x188, dword);
1164 } else {
1165 dword = pci_read_config32(NODE_PCI(node, 4), 0x128);
1166 dword &= ~(0x1 << 31); /* CstateMsgDis = 0 */
1167 pci_write_config32(NODE_PCI(node, 4), 0x128, dword);
1168 }
1169
1170 dword = pci_read_config32(NODE_PCI(node, 3), 0xd4);
1171 dword |= 0x1 << 13; /* MTC1eEn = 1 */
1172 pci_write_config32(NODE_PCI(node, 3), 0xd4, dword);
1173 }
1174
Timothy Pearson965704a2015-08-07 19:04:49 -05001175 if (revision & AMD_FAM15_ALL) {
1176 uint32_t f5x80;
1177 uint8_t cu_enabled;
1178 uint8_t compute_unit_count = 0;
1179 uint8_t compute_unit_buffer_count;
1180
Timothy Pearson71b8f012015-08-07 23:59:17 -05001181 uint32_t f3xe8;
1182 uint8_t dual_node = 0;
1183
1184 f3xe8 = pci_read_config32(NODE_PCI(0, 3), 0xe8);
1185
1186 /* Check for dual node capability */
1187 if (f3xe8 & 0x20000000)
1188 dual_node = 1;
1189
Timothy Pearson965704a2015-08-07 19:04:49 -05001190 /* Determine the number of active compute units on this node */
1191 f5x80 = pci_read_config32(NODE_PCI(node, 5), 0x80);
1192 cu_enabled = f5x80 & 0xf;
1193 if (cu_enabled == 0x1)
1194 compute_unit_count = 1;
1195 if (cu_enabled == 0x3)
1196 compute_unit_count = 2;
1197 if (cu_enabled == 0x7)
1198 compute_unit_count = 3;
1199 if (cu_enabled == 0xf)
1200 compute_unit_count = 4;
1201
1202 if (compute_unit_count == 1)
1203 compute_unit_buffer_count = 0x1c;
1204 else if (compute_unit_count == 2)
1205 compute_unit_buffer_count = 0x18;
1206 else if (compute_unit_count == 3)
1207 compute_unit_buffer_count = 0x14;
1208 else
1209 compute_unit_buffer_count = 0x10;
1210
1211 dword = pci_read_config32(NODE_PCI(node, 3), 0x1a0);
1212 dword &= ~(0x1f << 4); /* L3FreeListCBC = compute_unit_buffer_count */
1213 dword |= (compute_unit_buffer_count << 4);
1214 pci_write_config32(NODE_PCI(node, 3), 0x1a0, dword);
Timothy Pearson71b8f012015-08-07 23:59:17 -05001215
Timothy Pearsona52d5d12015-08-08 20:30:36 -05001216 uint8_t link;
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001217 uint8_t link_real;
Timothy Pearsona52d5d12015-08-08 20:30:36 -05001218 uint8_t ganged;
1219 uint8_t iolink;
1220 uint8_t probe_filter_enabled = !!dual_node;
1221
1222 /* Set up the Link Base Channel Buffer Count */
1223 uint8_t isoc_rsp_data;
1224 uint8_t isoc_np_req_data;
1225 uint8_t isoc_rsp_cmd;
1226 uint8_t isoc_preq;
1227 uint8_t isoc_np_req_cmd;
1228 uint8_t free_data;
1229 uint8_t free_cmd;
1230 uint8_t rsp_data;
1231 uint8_t np_req_data;
1232 uint8_t probe_cmd;
1233 uint8_t rsp_cmd;
1234 uint8_t preq;
1235 uint8_t np_req_cmd;
1236
1237 /* Common settings for all links and system configurations */
1238 isoc_rsp_data = 0;
1239 isoc_np_req_data = 0;
1240 isoc_rsp_cmd = 0;
1241 isoc_preq = 0;
1242 isoc_np_req_cmd = 1;
1243 free_cmd = 8;
1244
1245 for (link = 0; link < 4; link++) {
1246 if (AMD_CpuFindCapability(node, link, &offset)) {
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001247 link_real = (offset - 0x80) / 0x20;
1248 ganged = !!(pci_read_config32(NODE_PCI(node, 0), (link_real << 2) + 0x170) & 0x1);
1249 iolink = !!(AMD_checkLinkType(node, offset) & HTPHY_LINKTYPE_NONCOHERENT);
Timothy Pearsona52d5d12015-08-08 20:30:36 -05001250
1251 if (!iolink && ganged) {
1252 if (probe_filter_enabled) {
1253 free_data = 0;
1254 rsp_data = 3;
1255 np_req_data = 3;
1256 probe_cmd = 4;
1257 rsp_cmd = 9;
1258 preq = 2;
1259 np_req_cmd = 8;
1260 } else {
1261 free_data = 0;
1262 rsp_data = 3;
1263 np_req_data = 3;
1264 probe_cmd = 8;
1265 rsp_cmd = 9;
1266 preq = 2;
1267 np_req_cmd = 4;
1268 }
1269 } else if (!iolink && !ganged) {
1270 if (probe_filter_enabled) {
1271 free_data = 0;
1272 rsp_data = 3;
1273 np_req_data = 3;
1274 probe_cmd = 4;
1275 rsp_cmd = 9;
1276 preq = 2;
1277 np_req_cmd = 8;
1278 } else {
1279 free_data = 0;
1280 rsp_data = 3;
1281 np_req_data = 3;
1282 probe_cmd = 8;
1283 rsp_cmd = 9;
1284 preq = 2;
1285 np_req_cmd = 4;
1286 }
1287 } else if (iolink && ganged) {
1288 free_data = 0;
1289 rsp_data = 1;
1290 np_req_data = 0;
1291 probe_cmd = 0;
1292 rsp_cmd = 2;
1293 preq = 7;
1294 np_req_cmd = 14;
1295 } else {
1296 /* FIXME
1297 * This is an educated guess as the BKDG does not specify
1298 * the appropriate buffer counts for this case!
1299 */
1300 free_data = 1;
1301 rsp_data = 1;
1302 np_req_data = 1;
1303 probe_cmd = 0;
1304 rsp_cmd = 2;
1305 preq = 4;
1306 np_req_cmd = 12;
1307 }
1308
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001309 dword = pci_read_config32(NODE_PCI(node, 0), (link_real * 0x20) + 0x94);
Timothy Pearsona52d5d12015-08-08 20:30:36 -05001310 dword &= ~(0x3 << 27); /* IsocRspData = isoc_rsp_data */
1311 dword |= ((isoc_rsp_data & 0x3) << 27);
1312 dword &= ~(0x3 << 25); /* IsocNpReqData = isoc_np_req_data */
1313 dword |= ((isoc_np_req_data & 0x3) << 25);
1314 dword &= ~(0x7 << 22); /* IsocRspCmd = isoc_rsp_cmd */
1315 dword |= ((isoc_rsp_cmd & 0x7) << 22);
1316 dword &= ~(0x7 << 19); /* IsocPReq = isoc_preq */
1317 dword |= ((isoc_preq & 0x7) << 19);
1318 dword &= ~(0x7 << 16); /* IsocNpReqCmd = isoc_np_req_cmd */
1319 dword |= ((isoc_np_req_cmd & 0x7) << 16);
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001320 pci_write_config32(NODE_PCI(node, 0), (link_real * 0x20) + 0x94, dword);
Timothy Pearsona52d5d12015-08-08 20:30:36 -05001321
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001322 dword = pci_read_config32(NODE_PCI(node, 0), (link_real * 0x20) + 0x90);
Timothy Pearsona52d5d12015-08-08 20:30:36 -05001323 dword &= ~(0x1 << 31); /* LockBc = 0x1 */
1324 dword |= ((0x1 & 0x1) << 31);
1325 dword &= ~(0x7 << 25); /* FreeData = free_data */
1326 dword |= ((free_data & 0x7) << 25);
1327 dword &= ~(0x1f << 20); /* FreeCmd = free_cmd */
1328 dword |= ((free_cmd & 0x1f) << 20);
1329 dword &= ~(0x3 << 18); /* RspData = rsp_data */
1330 dword |= ((rsp_data & 0x3) << 18);
1331 dword &= ~(0x3 << 16); /* NpReqData = np_req_data */
1332 dword |= ((np_req_data & 0x3) << 16);
1333 dword &= ~(0xf << 12); /* ProbeCmd = probe_cmd */
1334 dword |= ((probe_cmd & 0xf) << 12);
1335 dword &= ~(0xf << 8); /* RspCmd = rsp_cmd */
1336 dword |= ((rsp_cmd & 0xf) << 8);
1337 dword &= ~(0x7 << 5); /* PReq = preq */
1338 dword |= ((preq & 0x7) << 5);
1339 dword &= ~(0x1f << 0); /* NpReqCmd = np_req_cmd */
1340 dword |= ((np_req_cmd & 0x1f) << 0);
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001341 pci_write_config32(NODE_PCI(node, 0), (link_real * 0x20) + 0x90, dword);
Timothy Pearsona52d5d12015-08-08 20:30:36 -05001342 }
1343 }
1344
Timothy Pearson71b8f012015-08-07 23:59:17 -05001345 /* Set up the Link to XCS Token Counts */
1346 uint8_t isoc_rsp_tok_1;
1347 uint8_t isoc_preq_tok_1;
1348 uint8_t isoc_req_tok_1;
1349 uint8_t probe_tok_1;
1350 uint8_t rsp_tok_1;
1351 uint8_t preq_tok_1;
1352 uint8_t req_tok_1;
1353 uint8_t isoc_rsp_tok_0;
1354 uint8_t isoc_preq_tok_0;
1355 uint8_t isoc_req_tok_0;
1356 uint8_t free_tokens;
1357 uint8_t probe_tok_0;
1358 uint8_t rsp_tok_0;
1359 uint8_t preq_tok_0;
1360 uint8_t req_tok_0;
1361
Timothy Pearson71b8f012015-08-07 23:59:17 -05001362 for (link = 0; link < 4; link++) {
1363 if (AMD_CpuFindCapability(node, link, &offset)) {
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001364 link_real = (offset - 0x80) / 0x20;
1365 ganged = !!(pci_read_config32(NODE_PCI(node, 0), (link_real << 2) + 0x170) & 0x1);
1366 iolink = !!(AMD_checkLinkType(node, offset) & HTPHY_LINKTYPE_NONCOHERENT);
Timothy Pearson71b8f012015-08-07 23:59:17 -05001367
1368 /* Set defaults */
1369 isoc_rsp_tok_1 = 0;
1370 isoc_preq_tok_1 = 0;
1371 isoc_req_tok_1 = 0;
1372 probe_tok_1 = !ganged;
1373 rsp_tok_1 = !ganged;
1374 preq_tok_1 = !ganged;
1375 req_tok_1 = !ganged;
1376 isoc_rsp_tok_0 = 0;
1377 isoc_preq_tok_0 = 0;
1378 isoc_req_tok_0 = 0;
1379 free_tokens = 0;
1380 probe_tok_0 = ((ganged)?2:1);
1381 rsp_tok_0 = ((ganged)?2:1);
1382 preq_tok_0 = ((ganged)?2:1);
1383 req_tok_0 = ((ganged)?2:1);
1384
1385 if (!iolink && ganged) {
1386 if (!dual_node) {
1387 isoc_rsp_tok_1 = 0;
1388 isoc_preq_tok_1 = 0;
1389 isoc_req_tok_1 = 0;
1390 probe_tok_1 = 0;
1391 rsp_tok_1 = 0;
1392 preq_tok_1 = 0;
1393 req_tok_1 = 0;
1394 isoc_rsp_tok_0 = 0;
1395 isoc_preq_tok_0 = 0;
1396 isoc_req_tok_0 = 1;
1397 free_tokens = 3;
1398 probe_tok_0 = 2;
1399 rsp_tok_0 = 2;
1400 preq_tok_0 = 2;
1401 req_tok_0 = 2;
1402 } else {
1403 if ((sockets == 1)
1404 || ((sockets == 2) && (sockets_populated == 1))) {
1405 isoc_rsp_tok_1 = 0;
1406 isoc_preq_tok_1 = 0;
1407 isoc_req_tok_1 = 0;
1408 probe_tok_1 = 0;
1409 rsp_tok_1 = 0;
1410 preq_tok_1 = 0;
1411 req_tok_1 = 0;
1412 isoc_rsp_tok_0 = 0;
1413 isoc_preq_tok_0 = 0;
1414 isoc_req_tok_0 = 1;
1415 free_tokens = 0;
1416 probe_tok_0 = 2;
1417 rsp_tok_0 = 2;
1418 preq_tok_0 = 2;
1419 req_tok_0 = 2;
1420 } else if (((sockets == 2) && (sockets_populated == 2))
1421 || ((sockets == 4) && (sockets_populated == 2))) {
1422 isoc_rsp_tok_1 = 0;
1423 isoc_preq_tok_1 = 0;
1424 isoc_req_tok_1 = 0;
1425 probe_tok_1 = 0;
1426 rsp_tok_1 = 0;
1427 preq_tok_1 = 0;
1428 req_tok_1 = 0;
1429 isoc_rsp_tok_0 = 0;
1430 isoc_preq_tok_0 = 0;
1431 isoc_req_tok_0 = 1;
1432 free_tokens = 0;
1433 probe_tok_0 = 1;
1434 rsp_tok_0 = 2;
1435 preq_tok_0 = 2;
1436 req_tok_0 = 2;
1437 } else if ((sockets == 4) && (sockets_populated == 4)) {
1438 isoc_rsp_tok_1 = 0;
1439 isoc_preq_tok_1 = 0;
1440 isoc_req_tok_1 = 0;
1441 probe_tok_1 = 0;
1442 rsp_tok_1 = 0;
1443 preq_tok_1 = 0;
1444 req_tok_1 = 0;
1445 isoc_rsp_tok_0 = 0;
1446 isoc_preq_tok_0 = 0;
1447 isoc_req_tok_0 = 1;
1448 free_tokens = 0;
1449 probe_tok_0 = 2;
1450 rsp_tok_0 = 1;
1451 preq_tok_0 = 1;
1452 req_tok_0 = 2;
1453 }
1454 }
1455 } else if (!iolink && !ganged) {
1456 if ((sockets == 1)
1457 || ((sockets == 2) && (sockets_populated == 1))) {
1458 if (probe_filter_enabled) {
1459 isoc_rsp_tok_1 = 0;
1460 isoc_preq_tok_1 = 0;
1461 isoc_req_tok_1 = 0;
1462 probe_tok_1 = 1;
1463 rsp_tok_1 = 1;
1464 preq_tok_1 = 1;
1465 req_tok_1 = 1;
1466 isoc_rsp_tok_0 = 0;
1467 isoc_preq_tok_0 = 0;
1468 isoc_req_tok_0 = 1;
1469 free_tokens = 0;
1470 probe_tok_0 = 1;
1471 rsp_tok_0 = 2;
1472 preq_tok_0 = 1;
1473 req_tok_0 = 1;
1474 } else {
1475 isoc_rsp_tok_1 = 0;
1476 isoc_preq_tok_1 = 0;
1477 isoc_req_tok_1 = 0;
1478 probe_tok_1 = 1;
1479 rsp_tok_1 = 1;
1480 preq_tok_1 = 1;
1481 req_tok_1 = 1;
1482 isoc_rsp_tok_0 = 0;
1483 isoc_preq_tok_0 = 0;
1484 isoc_req_tok_0 = 1;
1485 free_tokens = 0;
1486 probe_tok_0 = 1;
1487 rsp_tok_0 = 1;
1488 preq_tok_0 = 1;
1489 req_tok_0 = 1;
1490 }
1491 } else if ((sockets == 2) && (sockets_populated == 2)) {
1492 isoc_rsp_tok_1 = 0;
1493 isoc_preq_tok_1 = 0;
1494 isoc_req_tok_1 = 1;
1495 probe_tok_1 = 1;
1496 rsp_tok_1 = 1;
1497 preq_tok_1 = 1;
1498 req_tok_1 = 1;
1499 isoc_rsp_tok_0 = 0;
1500 isoc_preq_tok_0 = 0;
1501 isoc_req_tok_0 = 1;
1502 free_tokens = 2;
1503 probe_tok_0 = 1;
1504 rsp_tok_0 = 1;
1505 preq_tok_0 = 1;
1506 req_tok_0 = 1;
1507 } else if ((sockets == 4) && (sockets_populated == 2)) {
1508 isoc_rsp_tok_1 = 0;
1509 isoc_preq_tok_1 = 0;
1510 isoc_req_tok_1 = 1;
1511 probe_tok_1 = 1;
1512 rsp_tok_1 = 1;
1513 preq_tok_1 = 1;
1514 req_tok_1 = 1;
1515 isoc_rsp_tok_0 = 0;
1516 isoc_preq_tok_0 = 0;
1517 isoc_req_tok_0 = 1;
1518 free_tokens = 4;
1519 probe_tok_0 = 1;
1520 rsp_tok_0 = 1;
1521 preq_tok_0 = 1;
1522 req_tok_0 = 1;
1523 } else if ((sockets == 4) && (sockets_populated == 4)) {
1524 isoc_rsp_tok_1 = 0;
1525 isoc_preq_tok_1 = 0;
1526 isoc_req_tok_1 = 1;
1527 probe_tok_1 = 1;
1528 rsp_tok_1 = 1;
1529 preq_tok_1 = 1;
1530 req_tok_1 = 1;
1531 isoc_rsp_tok_0 = 0;
1532 isoc_preq_tok_0 = 0;
1533 isoc_req_tok_0 = 1;
1534 free_tokens = 0;
1535 probe_tok_0 = 1;
1536 rsp_tok_0 = 1;
1537 preq_tok_0 = 1;
1538 req_tok_0 = 1;
1539 }
1540 } else if (iolink && ganged) {
1541 if (!dual_node) {
1542 isoc_rsp_tok_1 = 0;
1543 isoc_preq_tok_1 = 0;
1544 isoc_req_tok_1 = 0;
1545 probe_tok_1 = 0;
1546 rsp_tok_1 = 0;
1547 preq_tok_1 = 0;
1548 req_tok_1 = 0;
1549 isoc_rsp_tok_0 = 0;
1550 isoc_preq_tok_0 = 0;
1551 isoc_req_tok_0 = 1;
1552 free_tokens = 3;
1553 probe_tok_0 = 0;
1554 rsp_tok_0 = 2;
1555 preq_tok_0 = 2;
1556 req_tok_0 = 2;
1557 } else if ((sockets == 1)
1558 || (sockets == 2)
1559 || ((sockets == 4) && (sockets_populated == 2))) {
1560 isoc_rsp_tok_1 = 0;
1561 isoc_preq_tok_1 = 0;
1562 isoc_req_tok_1 = 0;
1563 probe_tok_1 = 0;
1564 rsp_tok_1 = 0;
1565 preq_tok_1 = 0;
1566 req_tok_1 = 0;
1567 isoc_rsp_tok_0 = 0;
1568 isoc_preq_tok_0 = 0;
1569 isoc_req_tok_0 = 1;
1570 free_tokens = 0;
1571 probe_tok_0 = 0;
1572 rsp_tok_0 = 2;
1573 preq_tok_0 = 2;
1574 req_tok_0 = 2;
1575 } else if ((sockets == 4) && (sockets_populated == 4)) {
1576 isoc_rsp_tok_1 = 0;
1577 isoc_preq_tok_1 = 0;
1578 isoc_req_tok_1 = 0;
1579 probe_tok_1 = 0;
1580 rsp_tok_1 = 0;
1581 preq_tok_1 = 0;
1582 req_tok_1 = 0;
1583 isoc_rsp_tok_0 = 0;
1584 isoc_preq_tok_0 = 0;
1585 isoc_req_tok_0 = 2;
1586 free_tokens = 0;
1587 probe_tok_0 = 2;
1588 rsp_tok_0 = 2;
1589 preq_tok_0 = 2;
1590 req_tok_0 = 2;
1591 }
1592 }
1593
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001594 dword = pci_read_config32(NODE_PCI(node, 3), (link_real << 2) + 0x148);
Timothy Pearson71b8f012015-08-07 23:59:17 -05001595 dword &= ~(0x3 << 30); /* FreeTok[3:2] = free_tokens[3:2] */
1596 dword |= (((free_tokens >> 2) & 0x3) << 30);
1597 dword &= ~(0x1 << 28); /* IsocRspTok1 = isoc_rsp_tok_1 */
1598 dword |= (((isoc_rsp_tok_1) & 0x1) << 28);
1599 dword &= ~(0x1 << 26); /* IsocPreqTok1 = isoc_preq_tok_1 */
1600 dword |= (((isoc_preq_tok_1) & 0x1) << 26);
1601 dword &= ~(0x1 << 24); /* IsocReqTok1 = isoc_req_tok_1 */
1602 dword |= (((isoc_req_tok_1) & 0x1) << 24);
1603 dword &= ~(0x3 << 22); /* ProbeTok1 = probe_tok_1 */
1604 dword |= (((probe_tok_1) & 0x3) << 22);
1605 dword &= ~(0x3 << 20); /* RspTok1 = rsp_tok_1 */
1606 dword |= (((rsp_tok_1) & 0x3) << 20);
1607 dword &= ~(0x3 << 18); /* PReqTok1 = preq_tok_1 */
1608 dword |= (((preq_tok_1) & 0x3) << 18);
1609 dword &= ~(0x3 << 16); /* ReqTok1 = req_tok_1 */
1610 dword |= (((req_tok_1) & 0x3) << 16);
1611 dword &= ~(0x3 << 14); /* FreeTok[1:0] = free_tokens[1:0] */
1612 dword |= (((free_tokens) & 0x3) << 14);
1613 dword &= ~(0x3 << 12); /* IsocRspTok0 = isoc_rsp_tok_0 */
1614 dword |= (((isoc_rsp_tok_0) & 0x3) << 12);
1615 dword &= ~(0x3 << 10); /* IsocPreqTok0 = isoc_preq_tok_0 */
1616 dword |= (((isoc_preq_tok_0) & 0x3) << 10);
1617 dword &= ~(0x3 << 8); /* IsocReqTok0 = isoc_req_tok_0 */
1618 dword |= (((isoc_req_tok_0) & 0x3) << 8);
1619 dword &= ~(0x3 << 6); /* ProbeTok0 = probe_tok_0 */
1620 dword |= (((probe_tok_0) & 0x3) << 6);
1621 dword &= ~(0x3 << 4); /* RspTok0 = rsp_tok_0 */
1622 dword |= (((rsp_tok_0) & 0x3) << 4);
1623 dword &= ~(0x3 << 2); /* PReqTok0 = preq_tok_0 */
1624 dword |= (((preq_tok_0) & 0x3) << 2);
1625 dword &= ~(0x3 << 0); /* ReqTok0 = req_tok_0 */
1626 dword |= (((req_tok_0) & 0x3) << 0);
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001627 pci_write_config32(NODE_PCI(node, 3), (link_real << 2) + 0x148, dword);
Timothy Pearson71b8f012015-08-07 23:59:17 -05001628 }
1629 }
Timothy Pearsonbaa1acd2015-08-08 22:14:59 -05001630
1631 /* Set up the SRI to XCS Token Count */
1632 uint8_t free_tok;
1633 uint8_t up_rsp_tok;
1634
1635 /* Set defaults */
1636 free_tok = 0xa;
1637 up_rsp_tok = 0x3;
1638
1639 if (!dual_node) {
1640 free_tok = 0xa;
1641 up_rsp_tok = 0x3;
1642 } else {
1643 if ((sockets == 1)
1644 || ((sockets == 2) && (sockets_populated == 1))) {
1645 if (probe_filter_enabled) {
1646 free_tok = 0x9;
1647 up_rsp_tok = 0x3;
1648 } else {
1649 free_tok = 0xa;
1650 up_rsp_tok = 0x3;
1651 }
1652 } else if ((sockets == 2) && (sockets_populated == 2)) {
1653 free_tok = 0xb;
1654 up_rsp_tok = 0x1;
1655 } else if ((sockets == 4) && (sockets_populated == 2)) {
1656 free_tok = 0xa;
1657 up_rsp_tok = 0x3;
1658 } else if ((sockets == 4) && (sockets_populated == 4)) {
1659 free_tok = 0x9;
1660 up_rsp_tok = 0x1;
1661 }
1662 }
1663
1664 dword = pci_read_config32(NODE_PCI(node, 3), 0x140);
1665 dword &= ~(0xf << 20); /* FreeTok = free_tok */
1666 dword |= ((free_tok & 0xf) << 20);
1667 dword &= ~(0x3 << 8); /* UpRspTok = up_rsp_tok */
1668 dword |= ((up_rsp_tok & 0x3) << 8);
1669 pci_write_config32(NODE_PCI(node, 3), 0x140, dword);
Timothy Pearson965704a2015-08-07 19:04:49 -05001670 }
1671
Timothy Pearson50001b82015-08-11 17:47:48 -05001672 uint8_t link;
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001673 uint8_t link_real;
Timothy Pearson50001b82015-08-11 17:47:48 -05001674 uint8_t isochronous;
1675 uint8_t isochronous_link_present;
1676
1677 /* Set up isochronous buffers if needed */
1678 isochronous_link_present = 0;
1679 if (revision & AMD_FAM15_ALL) {
1680 for (link = 0; link < 4; link++) {
1681 if (AMD_CpuFindCapability(node, link, &offset)) {
Timothy Pearsonf8549e82015-09-07 22:26:55 -05001682 link_real = (offset - 0x80) / 0x20;
1683 isochronous = (pci_read_config32(NODE_PCI(node, 0), (link_real * 0x20) + 0x84) >> 12) & 0x1;
Timothy Pearson50001b82015-08-11 17:47:48 -05001684
1685 if (isochronous)
1686 isochronous_link_present = 1;
1687 }
1688 }
1689 }
1690
1691 uint8_t free_tok;
1692 uint8_t up_rsp_cbc;
1693 uint8_t isoc_preq_cbc;
1694 uint8_t isoc_preq_tok;
1695 uint8_t xbar_to_sri_free_list_cbc;
1696 if (isochronous_link_present) {
1697 /* Adjust buffer counts */
1698 dword = pci_read_config32(NODE_PCI(node, 3), 0x70);
1699 isoc_preq_cbc = (dword >> 24) & 0x7;
1700 up_rsp_cbc = (dword >> 16) & 0x7;
1701 up_rsp_cbc--;
1702 isoc_preq_cbc++;
1703 dword &= ~(0x7 << 24); /* IsocPreqCBC = isoc_preq_cbc */
1704 dword |= ((isoc_preq_cbc & 0x7) << 24);
1705 dword &= ~(0x7 << 16); /* UpRspCBC = up_rsp_cbc */
1706 dword |= ((up_rsp_cbc & 0x7) << 16);
1707 pci_write_config32(NODE_PCI(node, 3), 0x70, dword);
1708
1709 dword = pci_read_config32(NODE_PCI(node, 3), 0x74);
1710 isoc_preq_cbc = (dword >> 24) & 0x7;
1711 isoc_preq_cbc++;
1712 dword &= ~(0x7 << 24); /* IsocPreqCBC = isoc_preq_cbc */
1713 dword |= (isoc_preq_cbc & 0x7) << 24;
1714 pci_write_config32(NODE_PCI(node, 3), 0x74, dword);
1715
1716 dword = pci_read_config32(NODE_PCI(node, 3), 0x7c);
1717 xbar_to_sri_free_list_cbc = dword & 0x1f;
1718 xbar_to_sri_free_list_cbc--;
1719 dword &= ~0x1f; /* Xbar2SriFreeListCBC = xbar_to_sri_free_list_cbc */
1720 dword |= xbar_to_sri_free_list_cbc & 0x1f;
1721 pci_write_config32(NODE_PCI(node, 3), 0x7c, dword);
1722
1723 dword = pci_read_config32(NODE_PCI(node, 3), 0x140);
1724 free_tok = (dword >> 20) & 0xf;
1725 isoc_preq_tok = (dword >> 14) & 0x3;
1726 free_tok--;
1727 isoc_preq_tok++;
1728 dword &= ~(0xf << 20); /* FreeTok = free_tok */
1729 dword |= ((free_tok & 0xf) << 20);
1730 dword &= ~(0x3 << 14); /* IsocPreqTok = isoc_preq_tok */
1731 dword |= ((isoc_preq_tok & 0x3) << 14);
1732 pci_write_config32(NODE_PCI(node, 3), 0x140, dword);
1733 }
1734
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001735 printk(BIOS_DEBUG, " done\n");
1736}
1737
1738#ifdef UNUSED_CODE
Timothy Pearson730a0432015-10-16 13:51:51 -05001739/* Clearing the MCA registers is apparently handled in the ramstage CPU Function 3 driver */
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001740static void cpuInitializeMCA(void)
1741{
1742 /* Clears Machine Check Architecture (MCA) registers, which power on
1743 * containing unknown data, on currently running processor.
1744 * This routine should only be executed on initial power on (cold boot),
1745 * not across a warm reset because valid data is present at that time.
1746 */
1747
1748 msr_t msr;
1749 u32 reg;
1750 u8 i;
1751
1752 if (cpuid_edx(1) & 0x4080) { /* MCE and MCA (edx[7] and edx[14]) */
1753 msr = rdmsr(MCG_CAP);
1754 if (msr.lo & MCG_CTL_P) { /* MCG_CTL_P bit is set? */
1755 msr.lo &= 0xFF;
1756 msr.lo--;
1757 msr.lo <<= 2; /* multiply the count by 4 */
1758 reg = MC0_STA + msr.lo;
1759 msr.lo = msr.hi = 0;
1760 for (i = 0; i < 4; i++) {
1761 wrmsr(reg, msr);
1762 reg -= 4; /* Touch status regs for each bank */
1763 }
1764 }
1765 }
1766}
1767#endif
1768
1769/**
1770 * finalize_node_setup()
1771 *
1772 * Do any additional post HT init
1773 *
1774 */
1775static void finalize_node_setup(struct sys_info *sysinfo)
1776{
1777 u8 i;
1778 u8 nodes = get_nodes();
Patrick Georgif3e85422010-10-26 15:11:45 +00001779 u32 reg;
Kyösti Mälkki239c3d32013-12-27 14:46:32 +02001780
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001781 /* read Node0 F0_0x64 bit [8:10] to find out SbLink # */
1782 reg = pci_read_config32(NODE_HT(0), 0x64);
1783 sysinfo->sblk = (reg >> 8) & 7;
1784 sysinfo->sbbusn = 0;
1785 sysinfo->nodes = nodes;
1786 sysinfo->sbdn = get_sbdn(sysinfo->sbbusn);
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001787
1788 for (i = 0; i < nodes; i++) {
1789 cpuSetAMDPCI(i);
1790 }
1791
Patrick Georgi76e81522010-11-16 21:25:29 +00001792#if CONFIG_SET_FIDVID
Scott Duplichan1ba2eee2010-10-19 04:58:49 +00001793 // Prep each node for FID/VID setup.
1794 prep_fid_change();
1795#endif
1796
1797#if CONFIG_MAX_PHYSICAL_CPUS > 1
1798 /* Skip the BSP, start at node 1 */
1799 for (i = 1; i < nodes; i++) {
1800 setup_remote_node(i);
1801 start_node(i);
1802 }
1803#endif
1804}
1805
1806#include "fidvid.c"