blob: c2d277ad3f88c51426ba1f9191d06bb76e0a4df2 [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 *
4 * Copyright (C) 2007 Advanced Micro Devices, Inc.
Evelyn Huang284409f2017-05-30 16:05:58 -06005 * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>,
6 * Raptor Engineering
Marc Jones8ae8c882007-12-19 01:32:08 +00007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
Marc Jones8ae8c882007-12-19 01:32:08 +000016 */
17
Elyes HAOUASd2b9ec12018-10-27 09:41:02 +020018#include <arch/cpu.h>
Patrick Georgi3d5bb232010-05-09 21:15:13 +000019#include <console/console.h>
Edwin Beasanteb50c7d2010-07-06 21:05:04 +000020#include <pc80/mc146818rtc.h>
Martin Roth5f46af62017-06-24 13:24:26 -060021#if IS_ENABLED(CONFIG_HAVE_OPTION_TABLE)
Stefan Reinauer10ec0fe2010-09-25 10:40:47 +000022#include "option_table.h"
23#endif
Marc Jones8ae8c882007-12-19 01:32:08 +000024
Marc Jones8ae8c882007-12-19 01:32:08 +000025#include "cpu/amd/quadcore/quadcore_id.c"
26
Damien Zammit75a3d1f2016-11-28 00:29:10 +110027u32 get_core_num_in_bsp(u32 nodeid)
Marc Jones8ae8c882007-12-19 01:32:08 +000028{
29 u32 dword;
Timothy Pearson730a0432015-10-16 13:51:51 -050030 if (is_fam15h()) {
31 /* Family 15h moved CmpCap to F5x84 [7:0] */
32 dword = pci_read_config32(NODE_PCI(nodeid, 5), 0x84);
33 dword &= 0xff;
34 } else {
35 dword = pci_read_config32(NODE_PCI(nodeid, 3), 0xe8);
36 dword >>= 12;
37 /* Bit 15 is CmpCap[2] since Revision D. */
38 if ((cpuid_ecx(0x80000008) & 0xff) > 3)
Evelyn Huang284409f2017-05-30 16:05:58 -060039 dword = ((dword & 8) >> 1) | (dword & 3);
Timothy Pearson730a0432015-10-16 13:51:51 -050040 else
Evelyn Huang284409f2017-05-30 16:05:58 -060041 dword &= 3;
Timothy Pearson730a0432015-10-16 13:51:51 -050042 }
Marc Jones8ae8c882007-12-19 01:32:08 +000043 return dword;
44}
45
Damien Zammit75a3d1f2016-11-28 00:29:10 +110046u8 set_apicid_cpuid_lo(void)
Marc Jones8ae8c882007-12-19 01:32:08 +000047{
48 // set the NB_CFG[54]=1; why the OS will be happy with that ???
49 msr_t msr;
50 msr = rdmsr(NB_CFG_MSR);
51 msr.hi |= (1<<(54-32)); // InitApicIdCpuIdLo
52 wrmsr(NB_CFG_MSR, msr);
53
54 return 1;
55}
Marc Jones8ae8c882007-12-19 01:32:08 +000056
Damien Zammit75a3d1f2016-11-28 00:29:10 +110057void real_start_other_core(uint32_t nodeid, uint32_t cores)
Marc Jones8ae8c882007-12-19 01:32:08 +000058{
Timothy Pearson730a0432015-10-16 13:51:51 -050059 ssize_t i;
60 uint32_t dword;
Marc Jones8ae8c882007-12-19 01:32:08 +000061
Evelyn Huang284409f2017-05-30 16:05:58 -060062 printk(BIOS_DEBUG,
63 "Start other core - nodeid: %02x cores: %02x\n", nodeid, cores);
Marc Jones8ae8c882007-12-19 01:32:08 +000064
65 /* set PCI_DEV(0, 0x18+nodeid, 3), 0x44 bit 27 to redirect all MC4
66 accesses and error logging to core0 */
67 dword = pci_read_config32(NODE_PCI(nodeid, 3), 0x44);
Timothy Pearson730a0432015-10-16 13:51:51 -050068 dword |= 1 << 30; /* SyncFloodOnDramAdrParErr=1 */
69 dword |= 1 << 27; /* NbMcaToMstCpuEn=1 */
70 dword |= 1 << 21; /* SyncFloodOnAnyUcErr=1 */
71 dword |= 1 << 20; /* SyncFloodOnWDT=1 */
72 dword |= 1 << 2; /* SyncFloodOnDramUcEcc=1 */
Marc Jones8ae8c882007-12-19 01:32:08 +000073 pci_write_config32(NODE_PCI(nodeid, 3), 0x44, dword);
Timothy Pearson730a0432015-10-16 13:51:51 -050074 if (is_fam15h()) {
75 uint32_t core_activation_flags = 0;
76 uint32_t active_cores = 0;
Marc Jones8ae8c882007-12-19 01:32:08 +000077
Evelyn Huang284409f2017-05-30 16:05:58 -060078 /* Set PCI_DEV(0, 0x18+nodeid, 0),
79 * 0x1dc bits 7:1 to start cores
80 */
Timothy Pearson730a0432015-10-16 13:51:51 -050081 dword = pci_read_config32(NODE_PCI(nodeid, 0), 0x1dc);
Evelyn Huang284409f2017-05-30 16:05:58 -060082 for (i = 1; i < cores + 1; i++)
Timothy Pearson730a0432015-10-16 13:51:51 -050083 core_activation_flags |= 1 << i;
Timothy Pearson730a0432015-10-16 13:51:51 -050084 /* Start the first core of each compute unit */
85 active_cores |= core_activation_flags & 0x55;
Evelyn Huang284409f2017-05-30 16:05:58 -060086 pci_write_config32(NODE_PCI(nodeid, 0), 0x1dc, dword
87 | active_cores);
Timothy Pearson730a0432015-10-16 13:51:51 -050088
89 /* Each core shares a single set of MTRR registers with
90 * another core in the same compute unit, therefore, it
91 * is important that one core in each CU starts in advance
92 * of the other in order to avoid one core stomping all over
93 * the other core's settings.
94 */
95
96 /* Wait for the first core of each compute unit to start... */
97 uint32_t timeout;
98 for (i = 1; i < cores + 1; i++) {
99 if (!(i & 0x1)) {
Evelyn Huang284409f2017-05-30 16:05:58 -0600100 uint32_t ap_apicid =
101 get_boot_apic_id(nodeid, i);
102 timeout = wait_cpu_state(ap_apicid,
103 F10_APSTATE_ASLEEP, F10_APSTATE_ASLEEP);
Timothy Pearson730a0432015-10-16 13:51:51 -0500104 }
105 }
106
107 /* Start the second core of each compute unit */
108 active_cores |= core_activation_flags & 0xaa;
Evelyn Huang284409f2017-05-30 16:05:58 -0600109 pci_write_config32(NODE_PCI(nodeid, 0), 0x1dc, dword |
110 active_cores);
Timothy Pearson730a0432015-10-16 13:51:51 -0500111 } else {
112 // set PCI_DEV(0, 0x18+nodeid, 0), 0x68 bit 5 to start core1
113 dword = pci_read_config32(NODE_PCI(nodeid, 0), 0x68);
114 dword |= 1 << 5;
115 pci_write_config32(NODE_PCI(nodeid, 0), 0x68, dword);
116
117 if (cores > 1) {
118 dword = pci_read_config32(NODE_PCI(nodeid, 0), 0x168);
Evelyn Huang284409f2017-05-30 16:05:58 -0600119 for (i = 0; i < cores - 1; i++)
Timothy Pearson730a0432015-10-16 13:51:51 -0500120 dword |= 1 << i;
Timothy Pearson730a0432015-10-16 13:51:51 -0500121 pci_write_config32(NODE_PCI(nodeid, 0), 0x168, dword);
122 }
Marc Jones8ae8c882007-12-19 01:32:08 +0000123 }
124}
125
Timothy Pearson0122afb2015-07-30 14:07:15 -0500126#if (!IS_ENABLED(CONFIG_CPU_AMD_MODEL_10XXX))
Marc Jones8ae8c882007-12-19 01:32:08 +0000127//it is running on core0 of node0
Marc Jones65e08042008-04-25 21:34:25 +0000128static void start_other_cores(void)
Marc Jones8ae8c882007-12-19 01:32:08 +0000129{
130 u32 nodes;
131 u32 nodeid;
132
Myles Watson4839e2c2010-04-08 15:06:44 +0000133 // disable multi_core
Patrick Georgib2517532011-05-10 21:53:13 +0000134 if (read_option(multi_core, 0) != 0) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000135 printk(BIOS_DEBUG, "Skip additional core init\n");
Marc Jones8ae8c882007-12-19 01:32:08 +0000136 return;
137 }
138
139 nodes = get_nodes();
140
141 for (nodeid = 0; nodeid < nodes; nodeid++) {
142 u32 cores = get_core_num_in_bsp(nodeid);
Evelyn Huang284409f2017-05-30 16:05:58 -0600143 printk(BIOS_DEBUG, "init node: %02x cores: %02x pass 1\n",
144 nodeid, cores);
145 if (cores > 0)
Marc Jones8ae8c882007-12-19 01:32:08 +0000146 real_start_other_core(nodeid, cores);
Marc Jones8ae8c882007-12-19 01:32:08 +0000147 }
Marc Jones8ae8c882007-12-19 01:32:08 +0000148}
Timothy Pearson0122afb2015-07-30 14:07:15 -0500149#endif