blob: 8125fb474fef8b2b9b36d98cf5d9d77e808a382b [file] [log] [blame]
Marc Jones8ae8c882007-12-19 01:32:08 +00001/*
Stefan Reinauer7e61e452008-01-18 10:35:56 +00002 * This file is part of the coreboot project.
Marc Jones8ae8c882007-12-19 01:32:08 +00003 *
Marc Jones8ae8c882007-12-19 01:32:08 +00004 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
Marc Jones8ae8c882007-12-19 01:32:08 +000012 */
13
Elyes HAOUASd2b9ec12018-10-27 09:41:02 +020014#include <arch/cpu.h>
Patrick Georgi3d5bb232010-05-09 21:15:13 +000015#include <console/console.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020016#include <device/pci_ops.h>
Edwin Beasanteb50c7d2010-07-06 21:05:04 +000017#include <pc80/mc146818rtc.h>
Julius Wernercd49cce2019-03-05 16:53:33 -080018#if CONFIG(HAVE_OPTION_TABLE)
Stefan Reinauer10ec0fe2010-09-25 10:40:47 +000019#include "option_table.h"
20#endif
Marc Jones8ae8c882007-12-19 01:32:08 +000021
Marc Jones8ae8c882007-12-19 01:32:08 +000022#include "cpu/amd/quadcore/quadcore_id.c"
23
Damien Zammit75a3d1f2016-11-28 00:29:10 +110024u32 get_core_num_in_bsp(u32 nodeid)
Marc Jones8ae8c882007-12-19 01:32:08 +000025{
26 u32 dword;
Timothy Pearson730a0432015-10-16 13:51:51 -050027 if (is_fam15h()) {
28 /* Family 15h moved CmpCap to F5x84 [7:0] */
29 dword = pci_read_config32(NODE_PCI(nodeid, 5), 0x84);
30 dword &= 0xff;
31 } else {
32 dword = pci_read_config32(NODE_PCI(nodeid, 3), 0xe8);
33 dword >>= 12;
34 /* Bit 15 is CmpCap[2] since Revision D. */
35 if ((cpuid_ecx(0x80000008) & 0xff) > 3)
Evelyn Huang284409f2017-05-30 16:05:58 -060036 dword = ((dword & 8) >> 1) | (dword & 3);
Timothy Pearson730a0432015-10-16 13:51:51 -050037 else
Evelyn Huang284409f2017-05-30 16:05:58 -060038 dword &= 3;
Timothy Pearson730a0432015-10-16 13:51:51 -050039 }
Marc Jones8ae8c882007-12-19 01:32:08 +000040 return dword;
41}
42
Damien Zammit75a3d1f2016-11-28 00:29:10 +110043u8 set_apicid_cpuid_lo(void)
Marc Jones8ae8c882007-12-19 01:32:08 +000044{
45 // set the NB_CFG[54]=1; why the OS will be happy with that ???
46 msr_t msr;
47 msr = rdmsr(NB_CFG_MSR);
48 msr.hi |= (1<<(54-32)); // InitApicIdCpuIdLo
49 wrmsr(NB_CFG_MSR, msr);
50
51 return 1;
52}
Marc Jones8ae8c882007-12-19 01:32:08 +000053
Damien Zammit75a3d1f2016-11-28 00:29:10 +110054void real_start_other_core(uint32_t nodeid, uint32_t cores)
Marc Jones8ae8c882007-12-19 01:32:08 +000055{
Timothy Pearson730a0432015-10-16 13:51:51 -050056 ssize_t i;
57 uint32_t dword;
Marc Jones8ae8c882007-12-19 01:32:08 +000058
Evelyn Huang284409f2017-05-30 16:05:58 -060059 printk(BIOS_DEBUG,
60 "Start other core - nodeid: %02x cores: %02x\n", nodeid, cores);
Marc Jones8ae8c882007-12-19 01:32:08 +000061
62 /* set PCI_DEV(0, 0x18+nodeid, 3), 0x44 bit 27 to redirect all MC4
63 accesses and error logging to core0 */
64 dword = pci_read_config32(NODE_PCI(nodeid, 3), 0x44);
Timothy Pearson730a0432015-10-16 13:51:51 -050065 dword |= 1 << 30; /* SyncFloodOnDramAdrParErr=1 */
66 dword |= 1 << 27; /* NbMcaToMstCpuEn=1 */
67 dword |= 1 << 21; /* SyncFloodOnAnyUcErr=1 */
68 dword |= 1 << 20; /* SyncFloodOnWDT=1 */
69 dword |= 1 << 2; /* SyncFloodOnDramUcEcc=1 */
Marc Jones8ae8c882007-12-19 01:32:08 +000070 pci_write_config32(NODE_PCI(nodeid, 3), 0x44, dword);
Timothy Pearson730a0432015-10-16 13:51:51 -050071 if (is_fam15h()) {
72 uint32_t core_activation_flags = 0;
73 uint32_t active_cores = 0;
Marc Jones8ae8c882007-12-19 01:32:08 +000074
Evelyn Huang284409f2017-05-30 16:05:58 -060075 /* Set PCI_DEV(0, 0x18+nodeid, 0),
76 * 0x1dc bits 7:1 to start cores
77 */
Timothy Pearson730a0432015-10-16 13:51:51 -050078 dword = pci_read_config32(NODE_PCI(nodeid, 0), 0x1dc);
Evelyn Huang284409f2017-05-30 16:05:58 -060079 for (i = 1; i < cores + 1; i++)
Timothy Pearson730a0432015-10-16 13:51:51 -050080 core_activation_flags |= 1 << i;
Timothy Pearson730a0432015-10-16 13:51:51 -050081 /* Start the first core of each compute unit */
82 active_cores |= core_activation_flags & 0x55;
Evelyn Huang284409f2017-05-30 16:05:58 -060083 pci_write_config32(NODE_PCI(nodeid, 0), 0x1dc, dword
84 | active_cores);
Timothy Pearson730a0432015-10-16 13:51:51 -050085
86 /* Each core shares a single set of MTRR registers with
87 * another core in the same compute unit, therefore, it
88 * is important that one core in each CU starts in advance
89 * of the other in order to avoid one core stomping all over
90 * the other core's settings.
91 */
92
93 /* Wait for the first core of each compute unit to start... */
Timothy Pearson730a0432015-10-16 13:51:51 -050094 for (i = 1; i < cores + 1; i++) {
95 if (!(i & 0x1)) {
Evelyn Huang284409f2017-05-30 16:05:58 -060096 uint32_t ap_apicid =
97 get_boot_apic_id(nodeid, i);
Elyes HAOUASdedf66e2019-05-20 12:35:48 +020098 /* Timeout */
99 wait_cpu_state(ap_apicid, F10_APSTATE_ASLEEP,
100 F10_APSTATE_ASLEEP);
Timothy Pearson730a0432015-10-16 13:51:51 -0500101 }
102 }
103
104 /* Start the second core of each compute unit */
105 active_cores |= core_activation_flags & 0xaa;
Evelyn Huang284409f2017-05-30 16:05:58 -0600106 pci_write_config32(NODE_PCI(nodeid, 0), 0x1dc, dword |
107 active_cores);
Timothy Pearson730a0432015-10-16 13:51:51 -0500108 } else {
109 // set PCI_DEV(0, 0x18+nodeid, 0), 0x68 bit 5 to start core1
110 dword = pci_read_config32(NODE_PCI(nodeid, 0), 0x68);
111 dword |= 1 << 5;
112 pci_write_config32(NODE_PCI(nodeid, 0), 0x68, dword);
113
114 if (cores > 1) {
115 dword = pci_read_config32(NODE_PCI(nodeid, 0), 0x168);
Evelyn Huang284409f2017-05-30 16:05:58 -0600116 for (i = 0; i < cores - 1; i++)
Timothy Pearson730a0432015-10-16 13:51:51 -0500117 dword |= 1 << i;
Timothy Pearson730a0432015-10-16 13:51:51 -0500118 pci_write_config32(NODE_PCI(nodeid, 0), 0x168, dword);
119 }
Marc Jones8ae8c882007-12-19 01:32:08 +0000120 }
121}
122
Julius Wernercd49cce2019-03-05 16:53:33 -0800123#if (!CONFIG(CPU_AMD_MODEL_10XXX))
Marc Jones8ae8c882007-12-19 01:32:08 +0000124//it is running on core0 of node0
Marc Jones65e08042008-04-25 21:34:25 +0000125static void start_other_cores(void)
Marc Jones8ae8c882007-12-19 01:32:08 +0000126{
127 u32 nodes;
128 u32 nodeid;
129
Myles Watson4839e2c2010-04-08 15:06:44 +0000130 // disable multi_core
Patrick Georgib2517532011-05-10 21:53:13 +0000131 if (read_option(multi_core, 0) != 0) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000132 printk(BIOS_DEBUG, "Skip additional core init\n");
Marc Jones8ae8c882007-12-19 01:32:08 +0000133 return;
134 }
135
136 nodes = get_nodes();
137
138 for (nodeid = 0; nodeid < nodes; nodeid++) {
139 u32 cores = get_core_num_in_bsp(nodeid);
Evelyn Huang284409f2017-05-30 16:05:58 -0600140 printk(BIOS_DEBUG, "init node: %02x cores: %02x pass 1\n",
141 nodeid, cores);
142 if (cores > 0)
Marc Jones8ae8c882007-12-19 01:32:08 +0000143 real_start_other_core(nodeid, cores);
Marc Jones8ae8c882007-12-19 01:32:08 +0000144 }
Marc Jones8ae8c882007-12-19 01:32:08 +0000145}
Timothy Pearson0122afb2015-07-30 14:07:15 -0500146#endif