Marc Jones | 8ae8c88 | 2007-12-19 01:32:08 +0000 | [diff] [blame] | 1 | /* |
Stefan Reinauer | 7e61e45 | 2008-01-18 10:35:56 +0000 | [diff] [blame] | 2 | * This file is part of the coreboot project. |
Marc Jones | 8ae8c88 | 2007-12-19 01:32:08 +0000 | [diff] [blame] | 3 | * |
| 4 | * Copyright (C) 2007 Advanced Micro Devices, Inc. |
Evelyn Huang | 284409f | 2017-05-30 16:05:58 -0600 | [diff] [blame] | 5 | * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, |
| 6 | * Raptor Engineering |
Marc Jones | 8ae8c88 | 2007-12-19 01:32:08 +0000 | [diff] [blame] | 7 | * |
| 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 Jones | 8ae8c88 | 2007-12-19 01:32:08 +0000 | [diff] [blame] | 16 | */ |
| 17 | |
Elyes HAOUAS | d2b9ec1 | 2018-10-27 09:41:02 +0200 | [diff] [blame] | 18 | #include <arch/cpu.h> |
Patrick Georgi | 3d5bb23 | 2010-05-09 21:15:13 +0000 | [diff] [blame] | 19 | #include <console/console.h> |
Kyösti Mälkki | f1b58b7 | 2019-03-01 13:43:02 +0200 | [diff] [blame] | 20 | #include <device/pci_ops.h> |
Edwin Beasant | eb50c7d | 2010-07-06 21:05:04 +0000 | [diff] [blame] | 21 | #include <pc80/mc146818rtc.h> |
Martin Roth | 5f46af6 | 2017-06-24 13:24:26 -0600 | [diff] [blame] | 22 | #if IS_ENABLED(CONFIG_HAVE_OPTION_TABLE) |
Stefan Reinauer | 10ec0fe | 2010-09-25 10:40:47 +0000 | [diff] [blame] | 23 | #include "option_table.h" |
| 24 | #endif |
Marc Jones | 8ae8c88 | 2007-12-19 01:32:08 +0000 | [diff] [blame] | 25 | |
Marc Jones | 8ae8c88 | 2007-12-19 01:32:08 +0000 | [diff] [blame] | 26 | #include "cpu/amd/quadcore/quadcore_id.c" |
| 27 | |
Damien Zammit | 75a3d1f | 2016-11-28 00:29:10 +1100 | [diff] [blame] | 28 | u32 get_core_num_in_bsp(u32 nodeid) |
Marc Jones | 8ae8c88 | 2007-12-19 01:32:08 +0000 | [diff] [blame] | 29 | { |
| 30 | u32 dword; |
Timothy Pearson | 730a043 | 2015-10-16 13:51:51 -0500 | [diff] [blame] | 31 | 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 Huang | 284409f | 2017-05-30 16:05:58 -0600 | [diff] [blame] | 40 | dword = ((dword & 8) >> 1) | (dword & 3); |
Timothy Pearson | 730a043 | 2015-10-16 13:51:51 -0500 | [diff] [blame] | 41 | else |
Evelyn Huang | 284409f | 2017-05-30 16:05:58 -0600 | [diff] [blame] | 42 | dword &= 3; |
Timothy Pearson | 730a043 | 2015-10-16 13:51:51 -0500 | [diff] [blame] | 43 | } |
Marc Jones | 8ae8c88 | 2007-12-19 01:32:08 +0000 | [diff] [blame] | 44 | return dword; |
| 45 | } |
| 46 | |
Damien Zammit | 75a3d1f | 2016-11-28 00:29:10 +1100 | [diff] [blame] | 47 | u8 set_apicid_cpuid_lo(void) |
Marc Jones | 8ae8c88 | 2007-12-19 01:32:08 +0000 | [diff] [blame] | 48 | { |
| 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 Jones | 8ae8c88 | 2007-12-19 01:32:08 +0000 | [diff] [blame] | 57 | |
Damien Zammit | 75a3d1f | 2016-11-28 00:29:10 +1100 | [diff] [blame] | 58 | void real_start_other_core(uint32_t nodeid, uint32_t cores) |
Marc Jones | 8ae8c88 | 2007-12-19 01:32:08 +0000 | [diff] [blame] | 59 | { |
Timothy Pearson | 730a043 | 2015-10-16 13:51:51 -0500 | [diff] [blame] | 60 | ssize_t i; |
| 61 | uint32_t dword; |
Marc Jones | 8ae8c88 | 2007-12-19 01:32:08 +0000 | [diff] [blame] | 62 | |
Evelyn Huang | 284409f | 2017-05-30 16:05:58 -0600 | [diff] [blame] | 63 | printk(BIOS_DEBUG, |
| 64 | "Start other core - nodeid: %02x cores: %02x\n", nodeid, cores); |
Marc Jones | 8ae8c88 | 2007-12-19 01:32:08 +0000 | [diff] [blame] | 65 | |
| 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 Pearson | 730a043 | 2015-10-16 13:51:51 -0500 | [diff] [blame] | 69 | 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 Jones | 8ae8c88 | 2007-12-19 01:32:08 +0000 | [diff] [blame] | 74 | pci_write_config32(NODE_PCI(nodeid, 3), 0x44, dword); |
Timothy Pearson | 730a043 | 2015-10-16 13:51:51 -0500 | [diff] [blame] | 75 | if (is_fam15h()) { |
| 76 | uint32_t core_activation_flags = 0; |
| 77 | uint32_t active_cores = 0; |
Marc Jones | 8ae8c88 | 2007-12-19 01:32:08 +0000 | [diff] [blame] | 78 | |
Evelyn Huang | 284409f | 2017-05-30 16:05:58 -0600 | [diff] [blame] | 79 | /* Set PCI_DEV(0, 0x18+nodeid, 0), |
| 80 | * 0x1dc bits 7:1 to start cores |
| 81 | */ |
Timothy Pearson | 730a043 | 2015-10-16 13:51:51 -0500 | [diff] [blame] | 82 | dword = pci_read_config32(NODE_PCI(nodeid, 0), 0x1dc); |
Evelyn Huang | 284409f | 2017-05-30 16:05:58 -0600 | [diff] [blame] | 83 | for (i = 1; i < cores + 1; i++) |
Timothy Pearson | 730a043 | 2015-10-16 13:51:51 -0500 | [diff] [blame] | 84 | core_activation_flags |= 1 << i; |
Timothy Pearson | 730a043 | 2015-10-16 13:51:51 -0500 | [diff] [blame] | 85 | /* Start the first core of each compute unit */ |
| 86 | active_cores |= core_activation_flags & 0x55; |
Evelyn Huang | 284409f | 2017-05-30 16:05:58 -0600 | [diff] [blame] | 87 | pci_write_config32(NODE_PCI(nodeid, 0), 0x1dc, dword |
| 88 | | active_cores); |
Timothy Pearson | 730a043 | 2015-10-16 13:51:51 -0500 | [diff] [blame] | 89 | |
| 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 Huang | 284409f | 2017-05-30 16:05:58 -0600 | [diff] [blame] | 101 | 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 Pearson | 730a043 | 2015-10-16 13:51:51 -0500 | [diff] [blame] | 105 | } |
| 106 | } |
| 107 | |
| 108 | /* Start the second core of each compute unit */ |
| 109 | active_cores |= core_activation_flags & 0xaa; |
Evelyn Huang | 284409f | 2017-05-30 16:05:58 -0600 | [diff] [blame] | 110 | pci_write_config32(NODE_PCI(nodeid, 0), 0x1dc, dword | |
| 111 | active_cores); |
Timothy Pearson | 730a043 | 2015-10-16 13:51:51 -0500 | [diff] [blame] | 112 | } 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 Huang | 284409f | 2017-05-30 16:05:58 -0600 | [diff] [blame] | 120 | for (i = 0; i < cores - 1; i++) |
Timothy Pearson | 730a043 | 2015-10-16 13:51:51 -0500 | [diff] [blame] | 121 | dword |= 1 << i; |
Timothy Pearson | 730a043 | 2015-10-16 13:51:51 -0500 | [diff] [blame] | 122 | pci_write_config32(NODE_PCI(nodeid, 0), 0x168, dword); |
| 123 | } |
Marc Jones | 8ae8c88 | 2007-12-19 01:32:08 +0000 | [diff] [blame] | 124 | } |
| 125 | } |
| 126 | |
Timothy Pearson | 0122afb | 2015-07-30 14:07:15 -0500 | [diff] [blame] | 127 | #if (!IS_ENABLED(CONFIG_CPU_AMD_MODEL_10XXX)) |
Marc Jones | 8ae8c88 | 2007-12-19 01:32:08 +0000 | [diff] [blame] | 128 | //it is running on core0 of node0 |
Marc Jones | 65e0804 | 2008-04-25 21:34:25 +0000 | [diff] [blame] | 129 | static void start_other_cores(void) |
Marc Jones | 8ae8c88 | 2007-12-19 01:32:08 +0000 | [diff] [blame] | 130 | { |
| 131 | u32 nodes; |
| 132 | u32 nodeid; |
| 133 | |
Myles Watson | 4839e2c | 2010-04-08 15:06:44 +0000 | [diff] [blame] | 134 | // disable multi_core |
Patrick Georgi | b251753 | 2011-05-10 21:53:13 +0000 | [diff] [blame] | 135 | if (read_option(multi_core, 0) != 0) { |
Stefan Reinauer | c02b4fc | 2010-03-22 11:42:32 +0000 | [diff] [blame] | 136 | printk(BIOS_DEBUG, "Skip additional core init\n"); |
Marc Jones | 8ae8c88 | 2007-12-19 01:32:08 +0000 | [diff] [blame] | 137 | 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 Huang | 284409f | 2017-05-30 16:05:58 -0600 | [diff] [blame] | 144 | printk(BIOS_DEBUG, "init node: %02x cores: %02x pass 1\n", |
| 145 | nodeid, cores); |
| 146 | if (cores > 0) |
Marc Jones | 8ae8c88 | 2007-12-19 01:32:08 +0000 | [diff] [blame] | 147 | real_start_other_core(nodeid, cores); |
Marc Jones | 8ae8c88 | 2007-12-19 01:32:08 +0000 | [diff] [blame] | 148 | } |
Marc Jones | 8ae8c88 | 2007-12-19 01:32:08 +0000 | [diff] [blame] | 149 | } |
Timothy Pearson | 0122afb | 2015-07-30 14:07:15 -0500 | [diff] [blame] | 150 | #endif |