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.c77
1 files changed, 58 insertions, 19 deletions
diff --git a/src/cpu/amd/quadcore/quadcore_id.c b/src/cpu/amd/quadcore/quadcore_id.c
index cf45196cf1..c5921dee7f 100644
--- a/src/cpu/amd/quadcore/quadcore_id.c
+++ b/src/cpu/amd/quadcore/quadcore_id.c
@@ -1,6 +1,7 @@
/*
* This file is part of the coreboot project.
*
+ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
* Copyright (C) 2007 Advanced Micro Devices, Inc.
*
* This program is free software; you can redistribute it and/or modify
@@ -37,33 +38,71 @@ u32 get_initial_apicid(void)
return ((cpuid_ebx(1) >> 24) & 0xff);
}
-//called by amd_siblings too
-#define CORE_ID_BIT 2
-#define NODE_ID_BIT 6
+/* Called by amd_siblings (ramstage) as well */
struct node_core_id get_node_core_id(u32 nb_cfg_54)
{
struct node_core_id id;
- u32 core_id_bits;
+ uint8_t apicid;
+ uint8_t rev_gte_d = 0;
+ uint8_t dual_node = 0;
+ uint32_t f3xe8;
- u32 ApicIdCoreIdSize = (cpuid_ecx(0x80000008)>>12 & 0xf);
- if(ApicIdCoreIdSize) {
- core_id_bits = ApicIdCoreIdSize;
- } else {
- core_id_bits = CORE_ID_BIT; //quad core
- }
+#ifdef __PRE_RAM__
+ f3xe8 = pci_read_config32(NODE_PCI(0, 3), 0xe8);
+#else
+ f3xe8 = pci_read_config32(get_node_pci(0, 3), 0xe8);
+#endif
+
+ if (cpuid_eax(0x80000001) >= 0x8)
+ /* Revision D or later */
+ rev_gte_d = 1;
- // get the apicid via cpuid(1) ebx[31:24]
+ if (rev_gte_d)
+ /* Check for dual node capability */
+ if (f3xe8 & 0x20000000)
+ dual_node = 1;
+
+ /* Get the apicid via cpuid(1) ebx[31:24]
+ * The apicid format varies based on processor revision
+ */
+ apicid = (cpuid_ebx(1) >> 24) & 0xff;
if( nb_cfg_54) {
- // when NB_CFG[54] is set, nodeid = ebx[31:26], coreid = ebx[25:24]
- id.coreid = (cpuid_ebx(1) >> 24) & 0xff;
- id.nodeid = (id.coreid>>core_id_bits);
- id.coreid &= ((1<<core_id_bits)-1);
+ if (rev_gte_d && dual_node) {
+ id.coreid = apicid & 0xf;
+ id.nodeid = (apicid & 0x30) >> 4;
+ } else if (rev_gte_d && !dual_node) {
+ id.coreid = apicid & 0x7;
+ id.nodeid = (apicid & 0x38) >> 3;
+ } else {
+ id.coreid = apicid & 0x3;
+ id.nodeid = (apicid & 0x1c) >> 2;
+ }
} else {
- // when NB_CFG[54] is clear, nodeid = ebx[29:24], coreid = ebx[31:30]
- id.nodeid = (cpuid_ebx(1) >> 24) & 0xff;
- id.coreid = (id.nodeid>>NODE_ID_BIT);
- id.nodeid &= ((1<<NODE_ID_BIT)-1);
+ if (rev_gte_d && dual_node) {
+ id.coreid = (apicid & 0xf0) >> 4;
+ id.nodeid = apicid & 0x3;
+ } else if (rev_gte_d && !dual_node) {
+ id.coreid = (apicid & 0xe0) >> 5;
+ id.nodeid = apicid & 0x7;
+ } else {
+ id.coreid = (apicid & 0x60) >> 5;
+ id.nodeid = apicid & 0x7;
+ }
}
+
+ 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...
+ */
+ uint8_t core_count = (((f3xe8 & 0x00008000) >> 13) | ((f3xe8 & 0x00003000) >> 12)) + 1;
+
+ id.nodeid = id.nodeid * 2;
+ if (id.coreid >= core_count) {
+ id.nodeid += 1;
+ id.coreid = id.coreid - core_count;
+ }
+ }
+
return id;
}