blob: 47d9be9e6f7d7786c6bca0d3c574f6ba92a96875 [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 *
Evelyn Huang284409f2017-05-30 16:05:58 -06004 * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>,
5 * Raptor Engineering
Marc Jones8ae8c882007-12-19 01:32:08 +00006 * Copyright (C) 2007 Advanced Micro Devices, Inc.
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 Jones8ae8c882007-12-19 01:32:08 +000016 */
17
18
19#include <arch/cpu.h>
Stefan Reinauer9a16e3e2010-03-29 14:45:36 +000020#include <cpu/amd/multicore.h>
Myles Watson1d6d45e2009-11-06 17:02:51 +000021#ifdef __PRE_RAM__
Stefan Reinauer991f1842015-11-22 23:40:29 +010022#include <cpu/amd/msr.h>
Marc Jones8ae8c882007-12-19 01:32:08 +000023#endif
24
25//called by bus_cpu_scan too
26u32 read_nb_cfg_54(void)
27{
28 msr_t msr;
29 msr = rdmsr(NB_CFG_MSR);
Evelyn Huang284409f2017-05-30 16:05:58 -060030 return (msr.hi >> (54-32)) & 1;
Marc Jones8ae8c882007-12-19 01:32:08 +000031}
32
Stefan Reinauer817d7542010-07-08 00:37:23 +000033u32 get_initial_apicid(void)
Marc Jones8ae8c882007-12-19 01:32:08 +000034{
Evelyn Huang284409f2017-05-30 16:05:58 -060035 return (cpuid_ebx(1) >> 24) & 0xff;
Marc Jones8ae8c882007-12-19 01:32:08 +000036}
37
Timothy Pearson1c4508e2015-09-05 17:50:29 -050038/* Called by amd_siblings (ramstage) as well */
Marc Jones8ae8c882007-12-19 01:32:08 +000039struct node_core_id get_node_core_id(u32 nb_cfg_54)
40{
41 struct node_core_id id;
Timothy Pearson1c4508e2015-09-05 17:50:29 -050042 uint8_t apicid;
Timothy Pearson730a0432015-10-16 13:51:51 -050043 uint8_t fam15h = 0;
Timothy Pearson1c4508e2015-09-05 17:50:29 -050044 uint8_t rev_gte_d = 0;
45 uint8_t dual_node = 0;
46 uint32_t f3xe8;
Timothy Pearson730a0432015-10-16 13:51:51 -050047 uint32_t family;
48 uint32_t model;
Marc Jones8ae8c882007-12-19 01:32:08 +000049
Timothy Pearson1c4508e2015-09-05 17:50:29 -050050#ifdef __PRE_RAM__
51 f3xe8 = pci_read_config32(NODE_PCI(0, 3), 0xe8);
52#else
53 f3xe8 = pci_read_config32(get_node_pci(0, 3), 0xe8);
54#endif
Marc Jones8ae8c882007-12-19 01:32:08 +000055
Timothy Pearson730a0432015-10-16 13:51:51 -050056 family = model = cpuid_eax(0x80000001);
57 model = ((model & 0xf0000) >> 12) | ((model & 0xf0) >> 4);
58 family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);
59
60 if (family >= 0x6f) {
61 /* Family 15h or later */
62 fam15h = 1;
63 nb_cfg_54 = 1;
64 }
65
66 if ((model >= 0x8) || fam15h)
Timothy Pearson1c4508e2015-09-05 17:50:29 -050067 /* Revision D or later */
68 rev_gte_d = 1;
69
70 if (rev_gte_d)
71 /* Check for dual node capability */
72 if (f3xe8 & 0x20000000)
73 dual_node = 1;
74
75 /* Get the apicid via cpuid(1) ebx[31:24]
76 * The apicid format varies based on processor revision
77 */
78 apicid = (cpuid_ebx(1) >> 24) & 0xff;
Evelyn Huang284409f2017-05-30 16:05:58 -060079 if (nb_cfg_54) {
Timothy Pearson730a0432015-10-16 13:51:51 -050080 if (fam15h && dual_node) {
81 id.coreid = apicid & 0x1f;
82 id.nodeid = (apicid & 0x60) >> 5;
83 } else if (fam15h && !dual_node) {
84 id.coreid = apicid & 0xf;
85 id.nodeid = (apicid & 0x70) >> 4;
86 } else if (rev_gte_d && dual_node) {
Timothy Pearson1c4508e2015-09-05 17:50:29 -050087 id.coreid = apicid & 0xf;
88 id.nodeid = (apicid & 0x30) >> 4;
89 } else if (rev_gte_d && !dual_node) {
90 id.coreid = apicid & 0x7;
91 id.nodeid = (apicid & 0x38) >> 3;
92 } else {
93 id.coreid = apicid & 0x3;
94 id.nodeid = (apicid & 0x1c) >> 2;
95 }
Marc Jones8ae8c882007-12-19 01:32:08 +000096 } else {
Timothy Pearson1c4508e2015-09-05 17:50:29 -050097 if (rev_gte_d && dual_node) {
98 id.coreid = (apicid & 0xf0) >> 4;
99 id.nodeid = apicid & 0x3;
100 } else if (rev_gte_d && !dual_node) {
101 id.coreid = (apicid & 0xe0) >> 5;
102 id.nodeid = apicid & 0x7;
103 } else {
104 id.coreid = (apicid & 0x60) >> 5;
105 id.nodeid = apicid & 0x7;
106 }
Marc Jones8ae8c882007-12-19 01:32:08 +0000107 }
Timothy Pearson730a0432015-10-16 13:51:51 -0500108 if (fam15h && dual_node) {
Evelyn Huang284409f2017-05-30 16:05:58 -0600109 /* coreboot expects each separate processor die to be on a
110 * different nodeid.
111 * Since the code above returns nodeid 0 even on
112 * internal node 1 some fixup is needed...
Timothy Pearson730a0432015-10-16 13:51:51 -0500113 */
114 uint32_t f5x84;
115 uint8_t core_count;
116
117#ifdef __PRE_RAM__
118 f5x84 = pci_read_config32(NODE_PCI(0, 5), 0x84);
119#else
120 f5x84 = pci_read_config32(get_node_pci(0, 5), 0x84);
121#endif
122 core_count = (f5x84 & 0xff) + 1;
123 id.nodeid = id.nodeid * 2;
124 if (id.coreid >= core_count) {
125 id.nodeid += 1;
126 id.coreid = id.coreid - core_count;
127 }
128 } else if (rev_gte_d && dual_node) {
Evelyn Huang284409f2017-05-30 16:05:58 -0600129 /* coreboot expects each separate processor die to be on a
130 * different nodeid.
131 * Since the code above returns nodeid 0 even on
132 * internal node 1 some fixup is needed...
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500133 */
Evelyn Huang284409f2017-05-30 16:05:58 -0600134 uint8_t core_count = (((f3xe8 & 0x00008000) >> 13) |
135 ((f3xe8 & 0x00003000) >> 12)) + 1;
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500136
137 id.nodeid = id.nodeid * 2;
138 if (id.coreid >= core_count) {
139 id.nodeid += 1;
140 id.coreid = id.coreid - core_count;
141 }
142 }
143
Marc Jones8ae8c882007-12-19 01:32:08 +0000144 return id;
145}
146
Stefan Reinauer817d7542010-07-08 00:37:23 +0000147#ifdef UNUSED_CODE
Marc Jones65e08042008-04-25 21:34:25 +0000148static u32 get_core_num(void)
Marc Jones8ae8c882007-12-19 01:32:08 +0000149{
150 return (cpuid_ecx(0x80000008) & 0xff);
151}
Stefan Reinauer817d7542010-07-08 00:37:23 +0000152#endif
Marc Jones8ae8c882007-12-19 01:32:08 +0000153
Stefan Reinauer6f57b512010-07-08 16:41:05 +0000154struct node_core_id get_node_core_id_x(void)
Stefan Reinauer82144572009-04-15 06:00:01 +0000155{
156 return get_node_core_id(read_nb_cfg_54());
Marc Jones8ae8c882007-12-19 01:32:08 +0000157}