aboutsummaryrefslogtreecommitdiff
path: root/src/cpu/amd/quadcore/quadcore_id.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu/amd/quadcore/quadcore_id.c')
-rw-r--r--src/cpu/amd/quadcore/quadcore_id.c43
1 files changed, 40 insertions, 3 deletions
diff --git a/src/cpu/amd/quadcore/quadcore_id.c b/src/cpu/amd/quadcore/quadcore_id.c
index cd62a60a5b..acfdb4967a 100644
--- a/src/cpu/amd/quadcore/quadcore_id.c
+++ b/src/cpu/amd/quadcore/quadcore_id.c
@@ -39,9 +39,12 @@ struct node_core_id get_node_core_id(u32 nb_cfg_54)
{
struct node_core_id id;
uint8_t apicid;
+ uint8_t fam15h = 0;
uint8_t rev_gte_d = 0;
uint8_t dual_node = 0;
uint32_t f3xe8;
+ uint32_t family;
+ uint32_t model;
#ifdef __PRE_RAM__
f3xe8 = pci_read_config32(NODE_PCI(0, 3), 0xe8);
@@ -49,7 +52,17 @@ struct node_core_id get_node_core_id(u32 nb_cfg_54)
f3xe8 = pci_read_config32(get_node_pci(0, 3), 0xe8);
#endif
- if (cpuid_eax(0x80000001) >= 0x8)
+ family = model = cpuid_eax(0x80000001);
+ model = ((model & 0xf0000) >> 12) | ((model & 0xf0) >> 4);
+ family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);
+
+ if (family >= 0x6f) {
+ /* Family 15h or later */
+ fam15h = 1;
+ nb_cfg_54 = 1;
+ }
+
+ if ((model >= 0x8) || fam15h)
/* Revision D or later */
rev_gte_d = 1;
@@ -63,7 +76,13 @@ struct node_core_id get_node_core_id(u32 nb_cfg_54)
*/
apicid = (cpuid_ebx(1) >> 24) & 0xff;
if( nb_cfg_54) {
- if (rev_gte_d && dual_node) {
+ if (fam15h && dual_node) {
+ id.coreid = apicid & 0x1f;
+ id.nodeid = (apicid & 0x60) >> 5;
+ } else if (fam15h && !dual_node) {
+ id.coreid = apicid & 0xf;
+ id.nodeid = (apicid & 0x70) >> 4;
+ } else if (rev_gte_d && dual_node) {
id.coreid = apicid & 0xf;
id.nodeid = (apicid & 0x30) >> 4;
} else if (rev_gte_d && !dual_node) {
@@ -86,7 +105,25 @@ struct node_core_id get_node_core_id(u32 nb_cfg_54)
}
}
- if (rev_gte_d && dual_node) {
+ if (fam15h && dual_node) {
+ /* Coreboot expects each separate processor die to be on a different nodeid.
+ * Since the code above returns nodeid 0 even on internal node 1 some fixup is needed...
+ */
+ uint32_t f5x84;
+ uint8_t core_count;
+
+#ifdef __PRE_RAM__
+ f5x84 = pci_read_config32(NODE_PCI(0, 5), 0x84);
+#else
+ f5x84 = pci_read_config32(get_node_pci(0, 5), 0x84);
+#endif
+ core_count = (f5x84 & 0xff) + 1;
+ id.nodeid = id.nodeid * 2;
+ if (id.coreid >= core_count) {
+ id.nodeid += 1;
+ id.coreid = id.coreid - core_count;
+ }
+ } else if (rev_gte_d && dual_node) {
/* Coreboot expects each separate processor die to be on a different nodeid.
* Since the code above returns nodeid 0 even on internal node 1 some fixup is needed...
*/