blob: 601675123e9ed19f079f90b4a49cf2a408db52da [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>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020020#include <device/pci_ops.h>
Edwin Beasanteb50c7d2010-07-06 21:05:04 +000021#include <pc80/mc146818rtc.h>
Martin Roth5f46af62017-06-24 13:24:26 -060022#if IS_ENABLED(CONFIG_HAVE_OPTION_TABLE)
Stefan Reinauer10ec0fe2010-09-25 10:40:47 +000023#include "option_table.h"
24#endif
Marc Jones8ae8c882007-12-19 01:32:08 +000025
Marc Jones8ae8c882007-12-19 01:32:08 +000026#include "cpu/amd/quadcore/quadcore_id.c"
27
Damien Zammit75a3d1f2016-11-28 00:29:10 +110028u32 get_core_num_in_bsp(u32 nodeid)
Marc Jones8ae8c882007-12-19 01:32:08 +000029{
30 u32 dword;
Timothy Pearson730a0432015-10-16 13:51:51 -050031 if (is_fam15h()) {
32 /* Family 15h moved CmpCap to F5x84 [7:0] */
33 dword = pci_read_config32(NODE_PCI(nodeid, 5), 0x84);
34 dword &= 0xff;
35 } else {
36 dword = pci_read_config32(NODE_PCI(nodeid, 3), 0xe8);
37 dword >>= 12;
38 /* Bit 15 is CmpCap[2] since Revision D. */
39 if ((cpuid_ecx(0x80000008) & 0xff) > 3)
Evelyn Huang284409f2017-05-30 16:05:58 -060040 dword = ((dword & 8) >> 1) | (dword & 3);
Timothy Pearson730a0432015-10-16 13:51:51 -050041 else
Evelyn Huang284409f2017-05-30 16:05:58 -060042 dword &= 3;
Timothy Pearson730a0432015-10-16 13:51:51 -050043 }
Marc Jones8ae8c882007-12-19 01:32:08 +000044 return dword;
45}
46
Damien Zammit75a3d1f2016-11-28 00:29:10 +110047u8 set_apicid_cpuid_lo(void)
Marc Jones8ae8c882007-12-19 01:32:08 +000048{
49 // set the NB_CFG[54]=1; why the OS will be happy with that ???
50 msr_t msr;
51 msr = rdmsr(NB_CFG_MSR);
52 msr.hi |= (1<<(54-32)); // InitApicIdCpuIdLo
53 wrmsr(NB_CFG_MSR, msr);
54
55 return 1;
56}
Marc Jones8ae8c882007-12-19 01:32:08 +000057
Damien Zammit75a3d1f2016-11-28 00:29:10 +110058void real_start_other_core(uint32_t nodeid, uint32_t cores)
Marc Jones8ae8c882007-12-19 01:32:08 +000059{
Timothy Pearson730a0432015-10-16 13:51:51 -050060 ssize_t i;
61 uint32_t dword;
Marc Jones8ae8c882007-12-19 01:32:08 +000062
Evelyn Huang284409f2017-05-30 16:05:58 -060063 printk(BIOS_DEBUG,
64 "Start other core - nodeid: %02x cores: %02x\n", nodeid, cores);
Marc Jones8ae8c882007-12-19 01:32:08 +000065
66 /* set PCI_DEV(0, 0x18+nodeid, 3), 0x44 bit 27 to redirect all MC4
67 accesses and error logging to core0 */
68 dword = pci_read_config32(NODE_PCI(nodeid, 3), 0x44);
Timothy Pearson730a0432015-10-16 13:51:51 -050069 dword |= 1 << 30; /* SyncFloodOnDramAdrParErr=1 */
70 dword |= 1 << 27; /* NbMcaToMstCpuEn=1 */
71 dword |= 1 << 21; /* SyncFloodOnAnyUcErr=1 */
72 dword |= 1 << 20; /* SyncFloodOnWDT=1 */
73 dword |= 1 << 2; /* SyncFloodOnDramUcEcc=1 */
Marc Jones8ae8c882007-12-19 01:32:08 +000074 pci_write_config32(NODE_PCI(nodeid, 3), 0x44, dword);
Timothy Pearson730a0432015-10-16 13:51:51 -050075 if (is_fam15h()) {
76 uint32_t core_activation_flags = 0;
77 uint32_t active_cores = 0;
Marc Jones8ae8c882007-12-19 01:32:08 +000078
Evelyn Huang284409f2017-05-30 16:05:58 -060079 /* Set PCI_DEV(0, 0x18+nodeid, 0),
80 * 0x1dc bits 7:1 to start cores
81 */
Timothy Pearson730a0432015-10-16 13:51:51 -050082 dword = pci_read_config32(NODE_PCI(nodeid, 0), 0x1dc);
Evelyn Huang284409f2017-05-30 16:05:58 -060083 for (i = 1; i < cores + 1; i++)
Timothy Pearson730a0432015-10-16 13:51:51 -050084 core_activation_flags |= 1 << i;
Timothy Pearson730a0432015-10-16 13:51:51 -050085 /* Start the first core of each compute unit */
86 active_cores |= core_activation_flags & 0x55;
Evelyn Huang284409f2017-05-30 16:05:58 -060087 pci_write_config32(NODE_PCI(nodeid, 0), 0x1dc, dword
88 | active_cores);
Timothy Pearson730a0432015-10-16 13:51:51 -050089
90 /* Each core shares a single set of MTRR registers with
91 * another core in the same compute unit, therefore, it
92 * is important that one core in each CU starts in advance
93 * of the other in order to avoid one core stomping all over
94 * the other core's settings.
95 */
96
97 /* Wait for the first core of each compute unit to start... */
98 uint32_t timeout;
99 for (i = 1; i < cores + 1; i++) {
100 if (!(i & 0x1)) {
Evelyn Huang284409f2017-05-30 16:05:58 -0600101 uint32_t ap_apicid =
102 get_boot_apic_id(nodeid, i);
103 timeout = wait_cpu_state(ap_apicid,
104 F10_APSTATE_ASLEEP, F10_APSTATE_ASLEEP);
Timothy Pearson730a0432015-10-16 13:51:51 -0500105 }
106 }
107
108 /* Start the second core of each compute unit */
109 active_cores |= core_activation_flags & 0xaa;
Evelyn Huang284409f2017-05-30 16:05:58 -0600110 pci_write_config32(NODE_PCI(nodeid, 0), 0x1dc, dword |
111 active_cores);
Timothy Pearson730a0432015-10-16 13:51:51 -0500112 } else {
113 // set PCI_DEV(0, 0x18+nodeid, 0), 0x68 bit 5 to start core1
114 dword = pci_read_config32(NODE_PCI(nodeid, 0), 0x68);
115 dword |= 1 << 5;
116 pci_write_config32(NODE_PCI(nodeid, 0), 0x68, dword);
117
118 if (cores > 1) {
119 dword = pci_read_config32(NODE_PCI(nodeid, 0), 0x168);
Evelyn Huang284409f2017-05-30 16:05:58 -0600120 for (i = 0; i < cores - 1; i++)
Timothy Pearson730a0432015-10-16 13:51:51 -0500121 dword |= 1 << i;
Timothy Pearson730a0432015-10-16 13:51:51 -0500122 pci_write_config32(NODE_PCI(nodeid, 0), 0x168, dword);
123 }
Marc Jones8ae8c882007-12-19 01:32:08 +0000124 }
125}
126
Timothy Pearson0122afb2015-07-30 14:07:15 -0500127#if (!IS_ENABLED(CONFIG_CPU_AMD_MODEL_10XXX))
Marc Jones8ae8c882007-12-19 01:32:08 +0000128//it is running on core0 of node0
Marc Jones65e08042008-04-25 21:34:25 +0000129static void start_other_cores(void)
Marc Jones8ae8c882007-12-19 01:32:08 +0000130{
131 u32 nodes;
132 u32 nodeid;
133
Myles Watson4839e2c2010-04-08 15:06:44 +0000134 // disable multi_core
Patrick Georgib2517532011-05-10 21:53:13 +0000135 if (read_option(multi_core, 0) != 0) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000136 printk(BIOS_DEBUG, "Skip additional core init\n");
Marc Jones8ae8c882007-12-19 01:32:08 +0000137 return;
138 }
139
140 nodes = get_nodes();
141
142 for (nodeid = 0; nodeid < nodes; nodeid++) {
143 u32 cores = get_core_num_in_bsp(nodeid);
Evelyn Huang284409f2017-05-30 16:05:58 -0600144 printk(BIOS_DEBUG, "init node: %02x cores: %02x pass 1\n",
145 nodeid, cores);
146 if (cores > 0)
Marc Jones8ae8c882007-12-19 01:32:08 +0000147 real_start_other_core(nodeid, cores);
Marc Jones8ae8c882007-12-19 01:32:08 +0000148 }
Marc Jones8ae8c882007-12-19 01:32:08 +0000149}
Timothy Pearson0122afb2015-07-30 14:07:15 -0500150#endif