summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cpu/amd/model_10xxx/powernow_acpi.c36
1 files changed, 29 insertions, 7 deletions
diff --git a/src/cpu/amd/model_10xxx/powernow_acpi.c b/src/cpu/amd/model_10xxx/powernow_acpi.c
index d08f9f96d0..8b3ae37ba5 100644
--- a/src/cpu/amd/model_10xxx/powernow_acpi.c
+++ b/src/cpu/amd/model_10xxx/powernow_acpi.c
@@ -69,6 +69,13 @@ static void write_pstates_for_core(u8 pstate_num, u16 *pstate_feq, u32 *pstate_p
/*
* For details of this algorithm, please refer to the BDKG 3.62 page 69
+*
+* WARNING: The core count algorithm below assumes that all processors
+* are identical, with the same number of active cores. While the BKDG
+* states the BIOS must enforce this coreboot does not currently do so.
+* As a result it is possible that this code may break if an illegal
+* processor combination is installed. If it does break please fix the
+* code in the proper locations!
*/
static void pstates_algorithm(u32 pcontrol_blk, u8 plen, u8 onlyBSP)
{
@@ -106,15 +113,31 @@ static void pstates_algorithm(u32 pcontrol_blk, u8 plen, u8 onlyBSP)
processor_brand[48] = 0;
printk(BIOS_INFO, "processor_brand=%s\n", processor_brand);
+ uint32_t dtemp;
+ uint32_t cpuid_fms;
+ uint8_t model;
+ uint8_t node_count;
+
/*
* Based on the CPU socket type,cmp_cap and pwr_lmt , get the power limit.
* socket_type : 0x10 SocketF; 0x11 AM2/ASB1 ; 0x12 S1G1
- * cmp_cap : 0x0 SingleCore ; 0x1 DualCore ; 0x2 TripleCore ; 0x3 QuadCore ; 0x5 QuintupleCore ; 0x6 HexCore
+ * cmp_cap : 0x0 SingleCore ; 0x1 DualCore ; 0x2 TripleCore ; 0x3 QuadCore ; 0x4 QuintupleCore ; 0x5 HexCore
*/
- printk(BIOS_INFO, "Pstates Algorithm ...\n");
- cmp_cap =
- (pci_read_config16(dev_find_slot(0, PCI_DEVFN(0x18, 3)), 0xE8) &
- 0x7000) >> 12;
+ printk(BIOS_INFO, "Pstates algorithm ...\n");
+ /* Get CPU model */
+ cpuid_fms = cpuid_eax(0x80000001);
+ model = ((cpuid_fms & 0xf0000) >> 16) | ((cpuid_fms & 0xf0) >> 4);
+ /* Get number of cores */
+ dtemp = pci_read_config32(dev_find_slot(0, PCI_DEVFN(0x18, 3)), 0xE8);
+ cmp_cap = (dtemp & 0x3000) >> 12;
+ if ((model == 0x8) || (model == 0x9)) /* revision D */
+ cmp_cap |= (dtemp & 0x8000) >> 13;
+ /* Get number of nodes */
+ dtemp = pci_read_config32(dev_find_slot(0, PCI_DEVFN(0x18, 0)), 0x60);
+ node_count = ((dtemp & 0x70) >> 4) + 1;
+ /* Compute total number of cores installed in system */
+ cmp_cap++;
+ cmp_cap *= node_count;
Pstate_num = 0;
@@ -125,7 +148,6 @@ static void pstates_algorithm(u32 pcontrol_blk, u8 plen, u8 onlyBSP)
goto write_pstates;
}
- uint32_t dtemp;
uint8_t pviModeFlag;
uint8_t Pstate_max;
uint8_t cpufid;
@@ -237,7 +259,7 @@ static void pstates_algorithm(u32 pcontrol_blk, u8 plen, u8 onlyBSP)
}
write_pstates:
- for (index = 0; index < (cmp_cap + 1); index++)
+ for (index = 0; index < cmp_cap; index++)
write_pstates_for_core(Pstate_num, Pstate_feq, Pstate_power,
Pstate_latency, Pstate_control, Pstate_status,
index, pcontrol_blk, plen, onlyBSP);