From 83abd81c8acb3a53dfc125e248d9e5fd58f3e0f7 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Mon, 8 Jun 2015 19:35:06 -0500 Subject: cpu/amd: Add CC6 support This patch adds CC6 power save support to the AMD Family 15h support code. As CC6 is a complex power saving state that relies heavily on CPU, northbridge, and southbridge cooperation, this patch alters significant amounts of code throughout the tree simultaneously. Allowing the CPU to enter CC6 allows the second level of turbo boost to be reached, and also provides significant power savings when the system is idle due to the complete core shutdown. Change-Id: I44ce157cda97fb85f3e8f3d7262d4712b5410670 Signed-off-by: Timothy Pearson Reviewed-on: http://review.coreboot.org/11979 Tested-by: build bot (Jenkins) Tested-by: Raptor Engineering Automated Test Stand Reviewed-by: Stefan Reinauer Reviewed-by: Ronald G. Minnich --- src/cpu/amd/family_10h-family_15h/init_cpus.c | 81 +++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) (limited to 'src/cpu/amd/family_10h-family_15h/init_cpus.c') diff --git a/src/cpu/amd/family_10h-family_15h/init_cpus.c b/src/cpu/amd/family_10h-family_15h/init_cpus.c index 85eb931ce9..c9dca765c4 100644 --- a/src/cpu/amd/family_10h-family_15h/init_cpus.c +++ b/src/cpu/amd/family_10h-family_15h/init_cpus.c @@ -26,6 +26,14 @@ #include #include +#if IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB700) +#include +#endif + +#if IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB800) +#include +#endif + #if IS_ENABLED(CONFIG_SET_FIDVID) static void prep_fid_change(void); static void init_fidvid_stage2(u32 apicid, u32 nodeid); @@ -870,6 +878,7 @@ void cpuSetAMDMSR(uint8_t node_id) u8 i; u32 platform; uint64_t revision; + uint8_t enable_c_states; printk(BIOS_DEBUG, "cpuSetAMDMSR "); @@ -932,6 +941,44 @@ void cpuSetAMDMSR(uint8_t node_id) wrmsr(FP_CFG, msr); } +#if IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB700) || IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB800) + uint8_t nvram; + + if (revision & (AMD_DR_GT_D0 | AMD_FAM15_ALL)) { + /* Set up message triggered C1E */ + msr = rdmsr(0xc0010055); + msr.lo &= ~0xffff; /* IOMsgAddr = ACPI_PM_EVT_BLK */ + msr.lo |= ACPI_PM_EVT_BLK & 0xffff; + msr.lo |= (0x1 << 29); /* BmStsClrOnHltEn = 1 */ + if (revision & AMD_DR_GT_D0) { + msr.lo &= ~(0x1 << 28); /* C1eOnCmpHalt = 0 */ + msr.lo &= ~(0x1 << 27); /* SmiOnCmpHalt = 0 */ + } + wrmsr(0xc0010055, msr); + + msr = rdmsr(0xc0010015); + msr.lo |= (0x1 << 12); /* HltXSpCycEn = 1 */ + wrmsr(0xc0010015, msr); + } + + if (revision & (AMD_DR_Ex | AMD_FAM15_ALL)) { + enable_c_states = 0; + if (IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)) + if (get_option(&nvram, "cpu_c_states") == CB_SUCCESS) + enable_c_states = !!nvram; + + if (enable_c_states) { + /* Set up the C-state base address */ + msr_t c_state_addr_msr; + c_state_addr_msr = rdmsr(0xc0010073); + c_state_addr_msr.lo = ACPI_CPU_P_LVL2; /* CstateAddr = ACPI_CPU_P_LVL2 */ + wrmsr(0xc0010073, c_state_addr_msr); + } + } +#else + enable_c_states = 0; +#endif + printk(BIOS_DEBUG, " done\n"); } @@ -946,6 +993,7 @@ static void cpuSetAMDPCI(u8 node) u32 platform; u32 val; u8 offset; + uint32_t dword; uint64_t revision; printk(BIOS_DEBUG, "cpuSetAMDPCI %02d", node); @@ -1004,6 +1052,39 @@ static void cpuSetAMDPCI(u8 node) if (revision & (AMD_DR_B2 | AMD_DR_B3)) dctPhyDiag(); */ + if (revision & (AMD_DR_GT_D0 | AMD_FAM15_ALL)) { + /* Set up message triggered C1E */ + dword = pci_read_config32(NODE_PCI(node, 3), 0xd4); + dword &= ~(0x1 << 14); /* CacheFlushImmOnAllHalt = !is_fam15h() */ + dword |= (is_fam15h()?0:1) << 14; + pci_write_config32(NODE_PCI(node, 3), 0xd4, dword); + + dword = pci_read_config32(NODE_PCI(node, 3), 0xdc); + dword |= 0x1 << 26; /* IgnCpuPrbEn = 1 */ + dword &= ~(0x7f << 19); /* CacheFlushOnHaltTmr = 0x28 */ + dword |= 0x28 << 19; + dword |= 0x7 << 16; /* CacheFlushOnHaltCtl = 0x7 */ + pci_write_config32(NODE_PCI(node, 3), 0xdc, dword); + + dword = pci_read_config32(NODE_PCI(node, 3), 0xa0); + dword |= 0x1 << 10; /* IdleExitEn = 1 */ + pci_write_config32(NODE_PCI(node, 3), 0xa0, dword); + + if (revision & AMD_DR_GT_D0) { + dword = pci_read_config32(NODE_PCI(node, 3), 0x188); + dword |= 0x1 << 4; /* EnStpGntOnFlushMaskWakeup = 1 */ + pci_write_config32(NODE_PCI(node, 3), 0x188, dword); + } else { + dword = pci_read_config32(NODE_PCI(node, 4), 0x128); + dword &= ~(0x1 << 31); /* CstateMsgDis = 0 */ + pci_write_config32(NODE_PCI(node, 4), 0x128, dword); + } + + dword = pci_read_config32(NODE_PCI(node, 3), 0xd4); + dword |= 0x1 << 13; /* MTC1eEn = 1 */ + pci_write_config32(NODE_PCI(node, 3), 0xd4, dword); + } + printk(BIOS_DEBUG, " done\n"); } -- cgit v1.2.3