diff options
Diffstat (limited to 'resources/libreboot/patch/kgpe-d16/0046-cpu-amd-Add-CC6-support.patch')
-rw-r--r-- | resources/libreboot/patch/kgpe-d16/0046-cpu-amd-Add-CC6-support.patch | 1307 |
1 files changed, 1307 insertions, 0 deletions
diff --git a/resources/libreboot/patch/kgpe-d16/0046-cpu-amd-Add-CC6-support.patch b/resources/libreboot/patch/kgpe-d16/0046-cpu-amd-Add-CC6-support.patch new file mode 100644 index 00000000..026d8430 --- /dev/null +++ b/resources/libreboot/patch/kgpe-d16/0046-cpu-amd-Add-CC6-support.patch @@ -0,0 +1,1307 @@ +From 674911f61b4b32b0707962fa6a5a7e50811f721a Mon Sep 17 00:00:00 2001 +From: Timothy Pearson <tpearson@raptorengineeringinc.com> +Date: Mon, 8 Jun 2015 19:35:06 -0500 +Subject: [PATCH 046/139] cpu/amd: Add CC6 support + +Change-Id: I44ce157cda97fb85f3e8f3d7262d4712b5410670 +Signed-off-by: Timothy Pearson <tpearson@raptorengineeringinc.com> +--- + src/arch/x86/acpigen.c | 26 +++- + src/arch/x86/include/arch/acpigen.h | 3 + + src/cpu/amd/family_10h-family_15h/fidvid.c | 170 +++++++++++----------- + src/cpu/amd/family_10h-family_15h/init_cpus.c | 80 ++++++++++ + src/cpu/amd/family_10h-family_15h/powernow_acpi.c | 135 +++++++++++++++-- + src/include/cpu/amd/powernow.h | 2 + + src/mainboard/asus/kgpe-d16/cmos.default | 1 + + src/mainboard/asus/kgpe-d16/cmos.layout | 5 +- + src/northbridge/amd/amdfam10/link_control.c | 78 ++++++++++ + src/northbridge/amd/amdfam10/northbridge.c | 58 ++++---- + src/northbridge/amd/amdht/AsPsDefs.h | 3 +- + src/northbridge/amd/amdmct/amddefs.h | 66 +++++---- + src/northbridge/amd/amdmct/mct_ddr3/mct_d.c | 57 +++++--- + src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c | 8 + + src/southbridge/amd/sb700/early_setup.c | 20 ++- + src/southbridge/amd/sb700/fadt.c | 4 + + src/southbridge/amd/sb700/sb700.h | 7 +- + src/southbridge/amd/sb700/sm.c | 5 +- + src/southbridge/amd/sb800/fadt.c | 3 + + src/southbridge/amd/sb800/sb800.h | 8 +- + 20 files changed, 539 insertions(+), 200 deletions(-) + +diff --git a/src/arch/x86/acpigen.c b/src/arch/x86/acpigen.c +index 3aa823c..4136e65 100644 +--- a/src/arch/x86/acpigen.c ++++ b/src/arch/x86/acpigen.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) 2009 Rudolf Marek <r.marek@assembler.cz> + * + * This program is free software; you can redistribute it and/or modify +@@ -21,11 +22,11 @@ + #define ACPIGEN_LENSTACK_SIZE 10 + + /* +- * If you need to change this, change acpigen_write_f and ++ * If you need to change this, change acpigen_write_len_f and + * acpigen_pop_len + */ + +-#define ACPIGEN_MAXLEN 0xfff ++#define ACPIGEN_MAXLEN 0xfffff + + #include <string.h> + #include <arch/acpigen.h> +@@ -43,6 +44,7 @@ void acpigen_write_len_f(void) + len_stack[ltop++] = gencurrent; + acpigen_emit_byte(0); + acpigen_emit_byte(0); ++ acpigen_emit_byte(0); + } + + void acpigen_pop_len(void) +@@ -52,9 +54,10 @@ void acpigen_pop_len(void) + char *p = len_stack[--ltop]; + len = gencurrent - p; + ASSERT(len <= ACPIGEN_MAXLEN) +- /* generate store length for 0xfff max */ +- p[0] = (0x40 | (len & 0xf)); ++ /* generate store length for 0xfffff max */ ++ p[0] = (0x80 | (len & 0xf)); + p[1] = (len >> 4 & 0xff); ++ p[2] = (len >> 12 & 0xff); + + } + +@@ -483,6 +486,21 @@ void acpigen_write_CST_package(acpi_cstate_t *cstate, int nentries) + acpigen_pop_len(); + } + ++void acpigen_write_CSD_package(u32 domain, u32 numprocs, CSD_coord coordtype, u32 index) ++{ ++ acpigen_write_name("_CSD"); ++ acpigen_write_package(1); ++ acpigen_write_package(6); ++ acpigen_write_byte(6); // 6 values ++ acpigen_write_byte(0); // revision 0 ++ acpigen_write_dword(domain); ++ acpigen_write_dword(coordtype); ++ acpigen_write_dword(numprocs); ++ acpigen_write_dword(index); ++ acpigen_pop_len(); ++ acpigen_pop_len(); ++} ++ + void acpigen_write_TSS_package(int entries, acpi_tstate_t *tstate_list) + { + /* +diff --git a/src/arch/x86/include/arch/acpigen.h b/src/arch/x86/include/arch/acpigen.h +index a3e65eb..8e50960 100644 +--- a/src/arch/x86/include/arch/acpigen.h ++++ b/src/arch/x86/include/arch/acpigen.h +@@ -2,6 +2,7 @@ + * This file is part of the coreboot project. + * + * Copyright (C) 2009 Rudolf Marek <r.marek@assembler.cz> ++ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -55,6 +56,8 @@ typedef enum { SW_ALL=0xfc, SW_ANY=0xfd, HW_ALL=0xfe } PSD_coord; + void acpigen_write_PSD_package(u32 domain, u32 numprocs, PSD_coord coordtype); + void acpigen_write_CST_package_entry(acpi_cstate_t *cstate); + void acpigen_write_CST_package(acpi_cstate_t *entry, int nentries); ++typedef enum { CSD_HW_ALL=0xfe } CSD_coord; ++void acpigen_write_CSD_package(u32 domain, u32 numprocs, CSD_coord coordtype, u32 index); + void acpigen_write_processor(u8 cpuindex, u32 pblock_addr, u8 pblock_len); + void acpigen_write_TSS_package(int entries, acpi_tstate_t *tstate_list); + void acpigen_write_TSD_package(u32 domain, u32 numprocs, PSD_coord coordtype); +diff --git a/src/cpu/amd/family_10h-family_15h/fidvid.c b/src/cpu/amd/family_10h-family_15h/fidvid.c +index 2e26645..0e870e3 100644 +--- a/src/cpu/amd/family_10h-family_15h/fidvid.c ++++ b/src/cpu/amd/family_10h-family_15h/fidvid.c +@@ -169,87 +169,87 @@ static void applyBoostFIDOffset(device_t dev, uint32_t nodeid) { + } + + static void enableNbPState1( device_t dev ) { +- uint64_t cpuRev = mctGetLogicalCPUID(0xFF); +- if (cpuRev & AMD_FAM10_C3) { +- u32 nbPState = (pci_read_config32(dev, 0x1F0) & NB_PSTATE_MASK); +- if ( nbPState){ +- u32 nbVid1 = (pci_read_config32(dev, 0x1F4) & NB_VID1_MASK) >> NB_VID1_SHIFT; +- u32 i; +- for (i = nbPState; i < NM_PS_REG; i++) { +- msr_t msr = rdmsr(PS_REG_BASE + i); +- if (msr.hi & PS_EN_MASK ) { +- msr.hi |= NB_DID_M_ON; +- msr.lo &= NB_VID_MASK_OFF; +- msr.lo |= ( nbVid1 << NB_VID_POS); +- wrmsr(PS_REG_BASE + i, msr); +- } +- } +- } +- } ++ uint64_t cpuRev = mctGetLogicalCPUID(0xFF); ++ if (cpuRev & AMD_FAM10_C3) { ++ u32 nbPState = (pci_read_config32(dev, 0x1F0) & NB_PSTATE_MASK); ++ if ( nbPState){ ++ u32 nbVid1 = (pci_read_config32(dev, 0x1F4) & NB_VID1_MASK) >> NB_VID1_SHIFT; ++ u32 i; ++ for (i = nbPState; i < NM_PS_REG; i++) { ++ msr_t msr = rdmsr(PS_REG_BASE + i); ++ if (msr.hi & PS_EN_MASK ) { ++ msr.hi |= NB_DID_M_ON; ++ msr.lo &= NB_VID_MASK_OFF; ++ msr.lo |= ( nbVid1 << NB_VID_POS); ++ wrmsr(PS_REG_BASE + i, msr); ++ } ++ } ++ } ++ } + } + +-static u8 setPStateMaxVal( device_t dev ) { +- u8 i,maxpstate=0; +- for (i = 0; i < NM_PS_REG; i++) { +- msr_t msr = rdmsr(PS_REG_BASE + i); +- if (msr.hi & PS_IDD_VALUE_MASK) { +- msr.hi |= PS_EN_MASK ; +- wrmsr(PS_REG_BASE + i, msr); +- } +- if (msr.hi & PS_EN_MASK) { +- maxpstate = i; +- } +- } +- //FIXME: CPTC2 and HTC_REG should get max per node, not per core ? +- u32 reg = pci_read_config32(dev, CPTC2); +- reg &= PS_MAX_VAL_MASK; +- reg |= (maxpstate << PS_MAX_VAL_POS); +- pci_write_config32(dev, CPTC2,reg); +- return maxpstate; ++static u8 setPStateMaxVal(device_t dev) { ++ u8 i, maxpstate=0; ++ for (i = 0; i < NM_PS_REG; i++) { ++ msr_t msr = rdmsr(PS_REG_BASE + i); ++ if (msr.hi & PS_IDD_VALUE_MASK) { ++ msr.hi |= PS_EN_MASK ; ++ wrmsr(PS_REG_BASE + i, msr); ++ } ++ if (msr.hi & PS_EN_MASK) { ++ maxpstate = i; ++ } ++ } ++ //FIXME: CPTC2 and HTC_REG should get max per node, not per core ? ++ u32 reg = pci_read_config32(dev, CPTC2); ++ reg &= PS_MAX_VAL_MASK; ++ reg |= (maxpstate << PS_MAX_VAL_POS); ++ pci_write_config32(dev, CPTC2,reg); ++ return maxpstate; + } + + static void dualPlaneOnly( device_t dev ) { +- // BKDG 2.4.2.7 +- +- uint64_t cpuRev = mctGetLogicalCPUID(0xFF); +- if ((mctGetProcessorPackageType() == AMD_PKGTYPE_AM3_2r2) +- && (cpuRev & AMD_DR_Cx)) { // should be rev C or rev E but there's no constant for E +- if ( (pci_read_config32(dev, 0x1FC) & DUAL_PLANE_ONLY_MASK) +- && (pci_read_config32(dev, 0xA0) & PVI_MODE) ){ +- if (cpuid_edx(0x80000007) & CPB_MASK) { +- // revision E only, but E is apparently not supported yet, therefore untested +- msr_t minPstate = rdmsr(0xC0010065); +- wrmsr(0xC0010065, rdmsr(0xC0010068) ); +- wrmsr(0xC0010068,minPstate); +- } else { +- msr_t msr; +- msr.lo=0; msr.hi=0; +- wrmsr(0xC0010064, rdmsr(0xC0010068) ); +- wrmsr(0xC0010068, msr ); +- } +- +- //FIXME: CPTC2 and HTC_REG should get max per node, not per core ? +- u8 maxpstate = setPStateMaxVal(dev); +- +- u32 reg = pci_read_config32(dev, HTC_REG); +- reg &= HTC_PS_LMT_MASK; +- reg |= (maxpstate << PS_LIMIT_POS); +- pci_write_config32(dev, HTC_REG,reg); +- +- } +- } ++ // BKDG 2.4.2.7 ++ ++ uint64_t cpuRev = mctGetLogicalCPUID(0xFF); ++ if ((mctGetProcessorPackageType() == AMD_PKGTYPE_AM3_2r2) ++ && (cpuRev & (AMD_DR_Cx | AMD_DR_Ex))) { ++ if ((pci_read_config32(dev, 0x1FC) & DUAL_PLANE_ONLY_MASK) ++ && (pci_read_config32(dev, 0xA0) & PVI_MODE)) { ++ if (cpuid_edx(0x80000007) & CPB_MASK) { ++ // revision E only, but E is apparently not supported yet, therefore untested ++ msr_t minPstate = rdmsr(0xC0010065); ++ wrmsr(0xC0010065, rdmsr(0xC0010068)); ++ wrmsr(0xC0010068, minPstate); ++ } else { ++ msr_t msr; ++ msr.lo=0; msr.hi=0; ++ wrmsr(0xC0010064, rdmsr(0xC0010068) ); ++ wrmsr(0xC0010068, msr); ++ } ++ ++ //FIXME: CPTC2 and HTC_REG should get max per node, not per core ? ++ u8 maxpstate = setPStateMaxVal(dev); ++ ++ u32 reg = pci_read_config32(dev, HTC_REG); ++ reg &= HTC_PS_LMT_MASK; ++ reg |= (maxpstate << PS_LIMIT_POS); ++ pci_write_config32(dev, HTC_REG,reg); ++ } ++ } + } + + static int vidTo100uV(u8 vid) +-{// returns voltage corresponding to vid in tenths of mV, i.e. hundreds of uV +- // BKDG #31116 rev 3.48 2.4.1.6 +- int voltage; +- if (vid >= 0x7c) { +- voltage = 0; +- } else { +- voltage = (15500 - (125*vid)); +- } +- return voltage; ++{ ++ // returns voltage corresponding to vid in tenths of mV, i.e. hundreds of uV ++ // BKDG #31116 rev 3.48 2.4.1.6 ++ int voltage; ++ if (vid >= 0x7c) { ++ voltage = 0; ++ } else { ++ voltage = (15500 - (125*vid)); ++ } ++ return voltage; + } + + static void setVSRamp(device_t dev) { +@@ -348,7 +348,7 @@ static void recalculateVsSlamTimeSettingOnCorePre(device_t dev) + } + + /* Get AltVID */ +- dtemp = pci_read_config32(dev, 0xDC); ++ dtemp = pci_read_config32(dev, 0xdc); + bValue = (u8) (dtemp & BIT_MASK_7); + + /* Use the VID with the lowest voltage (higher VID) */ +@@ -512,15 +512,15 @@ static void config_nb_syn_ptr_adj(device_t dev, u32 cpuRev) { + values (min latency) */ + u32 nbPstate = pci_read_config32(dev,0x1f0) & NB_PSTATE_MASK; + u8 nbSynPtrAdj; +- if ((cpuRev & (AMD_DR_Bx|AMD_DA_Cx) ) +- || ( (cpuRev & AMD_RB_C3) && (nbPstate!=0))) { +- nbSynPtrAdj = 5; ++ if ((cpuRev & (AMD_DR_Bx | AMD_DA_Cx | AMD_FAM15_ALL) ) ++ || ((cpuRev & AMD_RB_C3) && (nbPstate != 0))) { ++ nbSynPtrAdj = 5; + } else { +- nbSynPtrAdj = 6; ++ nbSynPtrAdj = 6; + } + +- u32 dword = pci_read_config32(dev, 0xDc); +- dword &= ~ NB_SYN_PTR_ADJ_MASK; ++ u32 dword = pci_read_config32(dev, 0xdc); ++ dword &= ~NB_SYN_PTR_ADJ_MASK; + dword |= nbSynPtrAdj << NB_SYN_PTR_ADJ_POS; + /* NbsynPtrAdj set to 5 or 6 per BKDG (needs reset) */ + pci_write_config32(dev, 0xdc, dword); +@@ -552,7 +552,7 @@ static void config_acpi_pwr_state_ctrl_regs(device_t dev, u32 cpuRev, u8 procPkg + } + } else { // rev C or later + // same doubt as cache scrubbing: ok to check current state ? +- dword = pci_read_config32(dev, 0xDC); ++ dword = pci_read_config32(dev, 0xdc); + u32 cacheFlushOnHalt = dword & (7 << 16); + if (!cacheFlushOnHalt) { + c1 = 0x80; +@@ -623,11 +623,11 @@ static void prep_fid_change(void) + printk(BIOS_DEBUG, " F3x80: %08x\n", dword); + dword = pci_read_config32(dev, 0x84); + printk(BIOS_DEBUG, " F3x84: %08x\n", dword); +- dword = pci_read_config32(dev, 0xD4); ++ dword = pci_read_config32(dev, 0xd4); + printk(BIOS_DEBUG, " F3xD4: %08x\n", dword); +- dword = pci_read_config32(dev, 0xD8); ++ dword = pci_read_config32(dev, 0xd8); + printk(BIOS_DEBUG, " F3xD8: %08x\n", dword); +- dword = pci_read_config32(dev, 0xDC); ++ dword = pci_read_config32(dev, 0xdc); + printk(BIOS_DEBUG, " F3xDC: %08x\n", dword); + } + } +@@ -756,7 +756,7 @@ static void fixPsNbVidBeforeWR(u32 newNbVid, u32 coreid, u32 dev, u8 pviMode) + * synchronization between cores and we don't think + * PstatMaxVal is going to be 0 on cold reset anyway ? + */ +- if ( ! (pci_read_config32(dev, 0xDC) & (~ PS_MAX_VAL_MASK)) ) { ++ if (!(pci_read_config32(dev, 0xdc) & (~PS_MAX_VAL_MASK))) { + printk(BIOS_ERR,"F3xDC[PstateMaxVal] is zero. Northbridge voltage setting will fail. fixPsNbVidBeforeWR in fidvid.c needs fixing. See AMD # 31116 rev 3.48 BKDG 2.4.2.9.1 \n"); + }; + +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 aced850..818431b 100644 +--- a/src/cpu/amd/family_10h-family_15h/init_cpus.c ++++ b/src/cpu/amd/family_10h-family_15h/init_cpus.c +@@ -30,6 +30,14 @@ + #include <northbridge/amd/amdfam10/raminit_amdmct.c> + #include <reset.h> + ++#if IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB700) ++#include <southbridge/amd/sb700/sb700.h> ++#endif ++ ++#if IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB800) ++#include <southbridge/amd/sb800/sb800.h> ++#endif ++ + #if IS_ENABLED(CONFIG_SET_FIDVID) + static void prep_fid_change(void); + static void init_fidvid_stage2(u32 apicid, u32 nodeid); +@@ -874,6 +882,8 @@ void cpuSetAMDMSR(uint8_t node_id) + u8 i; + u32 platform; + uint64_t revision; ++ uint8_t nvram; ++ uint8_t enable_c_states; + + printk(BIOS_DEBUG, "cpuSetAMDMSR "); + +@@ -936,6 +946,42 @@ void cpuSetAMDMSR(uint8_t node_id) + wrmsr(FP_CFG, msr); + } + ++#if IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB700) || IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB800) ++ 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"); + } + +@@ -950,6 +996,7 @@ static void cpuSetAMDPCI(u8 node) + u32 platform; + u32 val; + u8 offset; ++ uint32_t dword; + uint64_t revision; + + printk(BIOS_DEBUG, "cpuSetAMDPCI %02d", node); +@@ -1008,6 +1055,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"); + } + +diff --git a/src/cpu/amd/family_10h-family_15h/powernow_acpi.c b/src/cpu/amd/family_10h-family_15h/powernow_acpi.c +index 84e5514..028ae3f 100644 +--- a/src/cpu/amd/family_10h-family_15h/powernow_acpi.c ++++ b/src/cpu/amd/family_10h-family_15h/powernow_acpi.c +@@ -21,6 +21,7 @@ + + #include <console/console.h> + #include <stdint.h> ++#include <option.h> + #include <cpu/x86/msr.h> + #include <arch/acpigen.h> + #include <cpu/amd/powernow.h> +@@ -34,21 +35,29 @@ + #include <northbridge/amd/amdmct/mct/mct.h> + #include <northbridge/amd/amdmct/amddefs.h> + ++static inline uint8_t is_fam15h(void) ++{ ++ uint8_t fam15h = 0; ++ uint32_t family; ++ ++ family = cpuid_eax(0x80000001); ++ family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8); ++ ++ if (family >= 0x6f) ++ /* Family 15h or later */ ++ fam15h = 1; ++ ++ return fam15h; ++} ++ + static void write_pstates_for_core(u8 pstate_num, u16 *pstate_feq, u32 *pstate_power, + u32 *pstate_latency, u32 *pstate_control, + u32 *pstate_status, int coreID, +- u32 pcontrol_blk, u8 plen, u8 onlyBSP, + uint8_t single_link) + { + int i; + struct cpuid_result cpuid1; + +- if ((onlyBSP) && (coreID != 0)) { +- plen = 0; +- pcontrol_blk = 0; +- } +- +- acpigen_write_processor(coreID, pcontrol_blk, plen); + acpigen_write_empty_PCT(); + acpigen_write_name("_PSS"); + +@@ -92,9 +101,62 @@ static void write_pstates_for_core(u8 pstate_num, u16 *pstate_feq, u32 *pstate_p + if (cpu) + acpigen_write_PSD_package(cpu->path.apic.apic_id, 1, SW_ANY); + } ++} + +- /* patch the whole Processor token length */ +- acpigen_pop_len(); ++static void write_cstates_for_core(int coreID) ++{ ++ /* Generate C state entries */ ++ uint8_t cstate_count = 1; ++ acpi_cstate_t cstate; ++ ++ if (is_fam15h()) { ++ cstate.ctype = 2; ++ cstate.latency = 100; ++ cstate.power = 0; ++ cstate.resource.space_id = ACPI_ADDRESS_SPACE_IO; ++ cstate.resource.bit_width = 8; ++ cstate.resource.bit_offset = 0; ++ cstate.resource.addrl = rdmsr(0xc0010073).lo + 1; ++ cstate.resource.addrh = 0; ++ cstate.resource.resv = 1; ++ } else { ++ cstate.ctype = 2; ++ cstate.latency = 75; ++ cstate.power = 0; ++ cstate.resource.space_id = ACPI_ADDRESS_SPACE_IO; ++ cstate.resource.bit_width = 8; ++ cstate.resource.bit_offset = 0; ++ cstate.resource.addrl = rdmsr(0xc0010073).lo; ++ cstate.resource.addrh = 0; ++ cstate.resource.resv = 1; ++ } ++ ++ acpigen_write_CST_package(&cstate, cstate_count); ++ ++ /* Find the local APIC ID for the specified core ID */ ++ if (is_fam15h()) { ++ struct device* cpu; ++ int cpu_index = 0; ++ for (cpu = all_devices; cpu; cpu = cpu->next) { ++ if ((cpu->path.type != DEVICE_PATH_APIC) || ++ (cpu->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER)) ++ continue; ++ if (!cpu->enabled) ++ continue; ++ if (cpu_index == coreID) ++ break; ++ cpu_index++; ++ } ++ ++ if (cpu) { ++ /* TODO ++ * Detect dual core status and skip CSD generation if dual core is disabled ++ */ ++ ++ /* Generate C state dependency entries */ ++ acpigen_write_CSD_package((cpu->path.apic.apic_id >> 1) & 0x7f, 2, CSD_HW_ALL, 0); ++ } ++ } + } + + /* +@@ -125,6 +187,15 @@ void amd_generate_powernow(u32 pcontrol_blk, u8 plen, u8 onlyBSP) + u8 index; + msr_t msr; + ++ uint8_t nvram; ++ uint8_t enable_c_states; ++ ++ enable_c_states = 0; ++#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES) ++ if (get_option(&nvram, "cpu_c_states") == CB_SUCCESS) ++ enable_c_states = !!nvram; ++#endif ++ + /* Get the Processor Brand String using cpuid(0x8000000x) command x=2,3,4 */ + cpuid1 = cpuid(0x80000002); + v = (u32 *) processor_brand; +@@ -200,6 +271,10 @@ void amd_generate_powernow(u32 pcontrol_blk, u8 plen, u8 onlyBSP) + return; + } + ++ if (fam15h) ++ /* Set P_LVL2 P_BLK entry */ ++ *(((uint8_t *)pcontrol_blk) + 0x04) = (rdmsr(0xc0010073).lo + 1) & 0xff; ++ + uint8_t pviModeFlag; + uint8_t Pstate_max; + uint8_t cpufid; +@@ -318,18 +393,56 @@ void amd_generate_powernow(u32 pcontrol_blk, u8 plen, u8 onlyBSP) + Pstate_latency[index]); + } + ++ /* Enter processor block scope */ + char pscope[] = "\\_PR"; +- + acpigen_write_scope(pscope); ++ + for (index = 0; index < total_core_count; index++) { + /* Determine if this is a single-link processor */ + node_index = 0x18 + (index / cores_per_node); + dtemp = pci_read_config32(dev_find_slot(0, PCI_DEVFN(node_index, 0)), 0x80); + single_link = !!(((dtemp & 0xff00) >> 8) == 0); + ++ /* Enter processor core scope */ ++ uint8_t plen_cur = plen; ++ uint32_t pcontrol_blk_cur = pcontrol_blk; ++ if ((onlyBSP) && (index != 0)) { ++ plen_cur = 0; ++ pcontrol_blk_cur = 0; ++ } ++ acpigen_write_processor(index, pcontrol_blk_cur, plen_cur); ++ ++ /* Write P-state status and dependency objects */ + write_pstates_for_core(Pstate_num, Pstate_feq, Pstate_power, + Pstate_latency, Pstate_control, Pstate_status, +- index, pcontrol_blk, plen, onlyBSP, single_link); ++ index, single_link); ++ ++ /* Write C-state status and dependency objects */ ++ if (fam15h && enable_c_states) ++ write_cstates_for_core(index); ++ ++ /* Exit processor core scope */ ++ acpigen_pop_len(); + } ++ ++ /* Exit processor block scope */ + acpigen_pop_len(); + } ++ ++void amd_powernow_update_fadt(acpi_fadt_t * fadt) ++{ ++ if (is_fam15h()) { ++ fadt->p_lvl2_lat = 101; /* NOTE: While the BKDG states this should ++ * be set to 100, there is no way to meet ++ * the other FADT requirements. I suspect ++ * there is an error in the BKDG for ACPI ++ * 1.x support; disable all FADT-based C ++ * states > 2... */ ++ fadt->p_lvl3_lat = 1001; ++ fadt->flags |= 0x1 << 2; /* FLAGS.PROC_C1 = 1 */ ++ fadt->flags |= 0x1 << 3; /* FLAGS.P_LVL2_UP = 1 */ ++ } else { ++ fadt->cst_cnt = 0; ++ } ++ fadt->pstate_cnt = 0; ++} +diff --git a/src/include/cpu/amd/powernow.h b/src/include/cpu/amd/powernow.h +index 85356bd..07817d9 100644 +--- a/src/include/cpu/amd/powernow.h ++++ b/src/include/cpu/amd/powernow.h +@@ -2,6 +2,7 @@ + * This file is part of the coreboot project. + * + * Copyright (C) 2009 Rudolf Marek <r.marek@assembler.cz> ++ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -21,5 +22,6 @@ + #define POWERNOW_H + + void amd_generate_powernow(u32 pcontrol_blk, u8 plen, u8 onlyBSP); ++void amd_powernow_update_fadt(acpi_fadt_t * fadt); + + #endif +diff --git a/src/mainboard/asus/kgpe-d16/cmos.default b/src/mainboard/asus/kgpe-d16/cmos.default +index bfd2020..e3eb4fe 100644 +--- a/src/mainboard/asus/kgpe-d16/cmos.default ++++ b/src/mainboard/asus/kgpe-d16/cmos.default +@@ -14,6 +14,7 @@ ecc_scrub_rate = 1.28us + interleave_chip_selects = Enable + interleave_nodes = Disable + interleave_memory_channels = Enable ++cpu_c_states = Enable + cpu_cc6_state = Enable + ieee1394 = Enable + power_on_after_fail = On +diff --git a/src/mainboard/asus/kgpe-d16/cmos.layout b/src/mainboard/asus/kgpe-d16/cmos.layout +index 630219e..7f9f661 100644 +--- a/src/mainboard/asus/kgpe-d16/cmos.layout ++++ b/src/mainboard/asus/kgpe-d16/cmos.layout +@@ -43,8 +43,9 @@ entries + 458 4 e 11 hypertransport_speed_limit + 462 2 e 12 minimum_memory_voltage + 464 1 e 2 compute_unit_siblings +-465 1 e 1 cpu_cc6_state +-466 1 r 0 allow_spd_nvram_cache_restore ++465 1 e 1 cpu_c_states ++466 1 e 1 cpu_cc6_state ++467 1 r 0 allow_spd_nvram_cache_restore + 477 1 e 1 ieee1394 + 728 256 h 0 user_data + 984 16 h 0 check_sum +diff --git a/src/northbridge/amd/amdfam10/link_control.c b/src/northbridge/amd/amdfam10/link_control.c +index 1091ef4..4acd66c 100644 +--- a/src/northbridge/amd/amdfam10/link_control.c ++++ b/src/northbridge/amd/amdfam10/link_control.c +@@ -49,15 +49,93 @@ static inline uint8_t is_fam15h(void) + + static void nb_control_init(struct device *dev) + { ++ uint8_t nvram; ++ uint8_t enable_c_states; ++ uint8_t enable_cc6; + uint32_t dword; + + printk(BIOS_DEBUG, "NB: Function 4 Link Control.. "); + ++ /* Configure L3 Power Control */ ++ dword = pci_read_config32(dev, 0x1c4); ++ dword |= (0x1 << 8); /* L3PwrSavEn = 1 */ ++ pci_write_config32(dev, 0x1c4, dword); ++ + if (is_fam15h()) { ++ /* Configure L3 Control 2 */ ++ dword = pci_read_config32(dev, 0x1cc); ++ dword &= ~(0x7 << 6); /* ImplRdProjDelayThresh = 0x2 */ ++ dword |= (0x2 << 6); ++ pci_write_config32(dev, 0x1cc, dword); ++ ++ /* Configure TDP Accumulator Divisor Control */ ++ dword = pci_read_config32(dev, 0x104); ++ dword &= ~(0xfff << 2); /* TdpAccDivRate = 0xc8 */ ++ dword |= (0xc8 << 2); ++ dword &= ~0x3; /* TdpAccDivVal = 0x1 */ ++ dword |= 0x1; ++ pci_write_config32(dev, 0x104, dword); ++ ++ /* Configure Sample and Residency Timers */ ++ dword = pci_read_config32(dev, 0x110); ++ dword &= ~0xfff; /* CSampleTimer = 0x1 */ ++ dword |= 0x1; ++ pci_write_config32(dev, 0x110, dword); ++ ++ /* Configure APM TDP Control */ ++ dword = pci_read_config32(dev, 0x16c); ++ dword |= (0x1 << 4); /* ApmTdpLimitIntEn = 1 */ ++ pci_write_config32(dev, 0x16c, dword); ++ + /* Enable APM */ + dword = pci_read_config32(dev, 0x15c); + dword |= (0x1 << 7); /* ApmMasterEn = 1 */ + pci_write_config32(dev, 0x15c, dword); ++ ++ enable_c_states = 0; ++ enable_cc6 = 0; ++#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES) ++ if (get_option(&nvram, "cpu_c_states") == CB_SUCCESS) ++ enable_c_states = !!nvram; ++ ++ if (get_option(&nvram, "cpu_cc6_state") == CB_SUCCESS) ++ enable_cc6 = !!nvram; ++#endif ++ ++ if (enable_c_states) { ++ /* Configure C-state Control 1 */ ++ dword = pci_read_config32(dev, 0x118); ++ dword |= (0x1 << 24); /* PwrGateEnCstAct1 = 1 */ ++ dword &= ~(0x7 << 21); /* ClkDivisorCstAct1 = 0x0 */ ++ dword &= ~(0x3 << 18); /* CacheFlushTmrSelCstAct1 = 0x1 */ ++ dword |= (0x1 << 18); ++ dword |= (0x1 << 17); /* CacheFlushEnCstAct1 = 1 */ ++ dword |= (0x1 << 16); /* CpuPrbEnCstAct1 = 1 */ ++ dword &= ~(0x1 << 8); /* PwrGateEnCstAct0 = 0 */ ++ dword &= ~(0x7 << 5); /* ClkDivisorCstAct0 = 0x0 */ ++ dword &= ~(0x3 << 2); /* CacheFlushTmrSelCstAct0 = 0x2 */ ++ dword |= (0x2 << 2); ++ dword |= (0x1 << 1); /* CacheFlushEnCstAct0 = 1 */ ++ dword |= 0x1; /* CpuPrbEnCstAct0 = 1 */ ++ pci_write_config32(dev, 0x118, dword); ++ ++ /* Configure C-state Control 2 */ ++ dword = pci_read_config32(dev, 0x11c); ++ dword &= ~(0x1 << 8); /* PwrGateEnCstAct2 = 0 */ ++ dword &= ~(0x7 << 5); /* ClkDivisorCstAct2 = 0x0 */ ++ dword &= ~(0x3 << 2); /* CacheFlushTmrSelCstAct0 = 0x0 */ ++ dword &= ~(0x1 << 1); /* CacheFlushEnCstAct0 = 0 */ ++ dword &= ~(0x1); /* CpuPrbEnCstAct0 = 0 */ ++ pci_write_config32(dev, 0x11c, dword); ++ ++ /* Configure C-state Policy Control 1 */ ++ dword = pci_read_config32(dev, 0x128); ++ dword &= ~(0x7f << 5); /* CacheFlushTmr = 0x28 */ ++ dword |= (0x28 << 5); ++ dword &= ~0x1; /* CoreCstateMode = !enable_cc6 */ ++ dword |= ((enable_cc6)?0:1); ++ pci_write_config32(dev, 0x128, dword); ++ } + } + + printk(BIOS_DEBUG, "done.\n"); +diff --git a/src/northbridge/amd/amdfam10/northbridge.c b/src/northbridge/amd/amdfam10/northbridge.c +index 51eac77..3fc31c0 100644 +--- a/src/northbridge/amd/amdfam10/northbridge.c ++++ b/src/northbridge/amd/amdfam10/northbridge.c +@@ -770,53 +770,49 @@ static void amdfam10_domain_read_resources(device_t dev) + uint8_t num_nodes; + + /* Find highest DRAM range (DramLimitAddr) */ ++ num_nodes = 0; + max_node = 0; + max_range = -1; + interleaved = 0; + max_range_limit = 0; +- for (range = 0; range < 8; range++) { +- dword = f1_read_config32(0x40 + (range * 0x8)); +- if (!(dword & 0x3)) +- continue; +- +- if ((dword >> 8) & 0x7) +- interleaved = 1; +- +- dword = f1_read_config32(0x44 + (range * 0x8)); +- dword2 = f1_read_config32(0x144 + (range * 0x8)); +- qword = ((((uint64_t)dword) >> 16) & 0xffff) << 24; +- qword |= (((uint64_t)dword2) & 0xff) << 40; +- +- if (qword > max_range_limit) { +- max_range = range; +- max_range_limit = qword; +- max_node = dword & 0x7; +- } +- } +- +- num_nodes = 0; + device_t node_dev; + for (node = 0; node < FX_DEVS; node++) { + node_dev = get_node_pci(node, 0); + /* Test for node presence */ +- if ((node_dev) && (pci_read_config32(node_dev, PCI_VENDOR_ID) != 0xffffffff)) +- num_nodes++; ++ if ((!node_dev) || (pci_read_config32(node_dev, PCI_VENDOR_ID) == 0xffffffff)) ++ continue; ++ ++ num_nodes++; ++ for (range = 0; range < 8; range++) { ++ dword = pci_read_config32(get_node_pci(node, 1), 0x40 + (range * 0x8)); ++ if (!(dword & 0x3)) ++ continue; ++ ++ if ((dword >> 8) & 0x7) ++ interleaved = 1; ++ ++ dword = pci_read_config32(get_node_pci(node, 1), 0x44 + (range * 0x8)); ++ dword2 = pci_read_config32(get_node_pci(node, 1), 0x144 + (range * 0x8)); ++ qword = 0xffffff; ++ qword |= ((((uint64_t)dword) >> 16) & 0xffff) << 24; ++ qword |= (((uint64_t)dword2) & 0xff) << 40; ++ ++ if (qword > max_range_limit) { ++ max_range = range; ++ max_range_limit = qword; ++ max_node = dword & 0x7; ++ } ++ } + } + +- /* Calculate CC6 sotrage area size */ ++ /* Calculate CC6 storage area size */ + if (interleaved) + qword = (0x1000000 * num_nodes); + else + qword = 0x1000000; + + /* Reserve the CC6 save segment */ +- reserved_ram_resource(dev, 8, max_range_limit >> 10, qword >> 10); +- +- /* Set up the C-state base address */ +- msr_t c_state_addr_msr; +- c_state_addr_msr = rdmsr(0xc0010073); +- c_state_addr_msr.lo = 0xe0e0; /* CstateAddr = 0xe0e0 */ +- wrmsr(0xc0010073, c_state_addr_msr); ++ reserved_ram_resource(dev, 8, (max_range_limit + 1) >> 10, qword >> 10); + } + } + } +diff --git a/src/northbridge/amd/amdht/AsPsDefs.h b/src/northbridge/amd/amdht/AsPsDefs.h +index caeb9b4..7f29dd1 100644 +--- a/src/northbridge/amd/amdht/AsPsDefs.h ++++ b/src/northbridge/amd/amdht/AsPsDefs.h +@@ -2,6 +2,7 @@ + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2008 Advanced Micro Devices, Inc. ++ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -254,7 +255,7 @@ + #define DUAL_PLANE_NB_VID_SHIFT 17/* for CPU rev <= C */ + + +-#define NM_PS_REG 5 /* number of P-state MSR registers */ ++#define NM_PS_REG (is_fam15h()?8:5) /* number of P-state MSR registers */ + + /* sFidVidInit.outFlags defines */ + #define PWR_CK_OK 0 /* System board check OK */ +diff --git a/src/northbridge/amd/amdmct/amddefs.h b/src/northbridge/amd/amdmct/amddefs.h +index 20a77d3..7aa4698 100644 +--- a/src/northbridge/amd/amdmct/amddefs.h ++++ b/src/northbridge/amd/amdmct/amddefs.h +@@ -53,32 +53,34 @@ + /* + * Groups - Create as many as you wish, from the above public values + */ +-#define AMD_NPT_F2 (AMD_NPT_F2C | AMD_NPT_F2D | AMD_NPT_F2E | AMD_NPT_F2G | AMD_NPT_F2J | AMD_NPT_F2K) +-#define AMD_NPT_F3 (AMD_NPT_F3L) +-#define AMD_NPT_Fx (AMD_NPT_F0 | AMD_NPT_F1 | AMD_NPT_F2 | AMD_NPT_F3) +-#define AMD_NPT_Gx (AMD_NPT_G0A | AMD_NPT_G1B) +-#define AMD_NPT_ALL (AMD_NPT_Fx | AMD_NPT_Gx) +-#define AMD_FINEDELAY (AMD_NPT_F0 | AMD_NPT_F1 | AMD_NPT_F2) +-#define AMD_GT_F0 (AMD_NPT_ALL AND NOT AMD_NPT_F0) +-#define AMD_DR_Ax (AMD_DR_A0A + AMD_DR_A1B + AMD_DR_A2) +-#define AMD_DR_Bx (AMD_DR_B0 | AMD_DR_B1 | AMD_DR_B2 | AMD_DR_B3 | AMD_DR_BA) +-#define AMD_DR_LT_B2 (AMD_DR_B0 | AMD_DR_B1 | AMD_DR_BA) +-#define AMD_DR_LT_B3 (AMD_DR_B0 | AMD_DR_B1 | AMD_DR_B2 | AMD_DR_BA) +-#define AMD_DR_GT_B0 (AMD_DR_ALL & ~(AMD_DR_B0)) +-#define AMD_DR_GT_Bx (AMD_DR_ALL & ~(AMD_DR_Ax | AMD_DR_Bx)) +-#define AMD_DR_ALL (AMD_DR_Bx) +-#define AMD_FAM10_ALL (AMD_DR_ALL | AMD_RB_C2 | AMD_HY_D0 | AMD_DA_C3 | AMD_DA_C2 | AMD_RB_C3 | AMD_HY_D1 | AMD_PH_E0) +-#define AMD_FAM10_LT_D (AMD_FAM10_ALL & ~(AMD_HY_D0)) +-#define AMD_FAM10_GT_B0 (AMD_FAM10_ALL & ~(AMD_DR_B0)) +-#define AMD_FAM10_REV_D (AMD_HY_D0 | AMD_HY_D1) +-#define AMD_DA_Cx (AMD_DA_C2 | AMD_DA_C3) +-#define AMD_DR_Cx (AMD_RB_C2 | AMD_RB_C3 | AMD_DA_Cx) +-#define AMD_FAM10_C3 (AMD_RB_C3 | AMD_DA_C3) +-#define AMD_DR_Dx (AMD_HY_D0 | AMD_HY_D1) +-#define AMD_DRBH_Cx (AMD_DR_Cx | AMD_HY_D0 ) +-#define AMD_DRBA23_RBC2 (AMD_DR_BA | AMD_DR_B2 | AMD_DR_B3 | AMD_RB_C2 ) ++#define AMD_NPT_F2 (AMD_NPT_F2C | AMD_NPT_F2D | AMD_NPT_F2E | AMD_NPT_F2G | AMD_NPT_F2J | AMD_NPT_F2K) ++#define AMD_NPT_F3 (AMD_NPT_F3L) ++#define AMD_NPT_Fx (AMD_NPT_F0 | AMD_NPT_F1 | AMD_NPT_F2 | AMD_NPT_F3) ++#define AMD_NPT_Gx (AMD_NPT_G0A | AMD_NPT_G1B) ++#define AMD_NPT_ALL (AMD_NPT_Fx | AMD_NPT_Gx) ++#define AMD_FINEDELAY (AMD_NPT_F0 | AMD_NPT_F1 | AMD_NPT_F2) ++#define AMD_GT_F0 (AMD_NPT_ALL AND NOT AMD_NPT_F0) ++#define AMD_DR_Ax (AMD_DR_A0A + AMD_DR_A1B + AMD_DR_A2) ++#define AMD_DR_Bx (AMD_DR_B0 | AMD_DR_B1 | AMD_DR_B2 | AMD_DR_B3 | AMD_DR_BA) ++#define AMD_DR_Cx (AMD_RB_C2 | AMD_RB_C3 | AMD_DA_Cx) ++#define AMD_DR_Dx (AMD_HY_D0 | AMD_HY_D1) ++#define AMD_DR_Ex (AMD_PH_E0) ++#define AMD_DR_LT_B2 (AMD_DR_B0 | AMD_DR_B1 | AMD_DR_BA) ++#define AMD_DR_LT_B3 (AMD_DR_B0 | AMD_DR_B1 | AMD_DR_B2 | AMD_DR_BA) ++#define AMD_DR_GT_B0 (AMD_DR_ALL & ~(AMD_DR_B0)) ++#define AMD_DR_GT_Bx (AMD_DR_ALL & ~(AMD_DR_Ax | AMD_DR_Bx)) ++#define AMD_DR_GT_D0 ((AMD_DR_Dx & ~(AMD_HY_D0)) | AMD_DR_Ex) ++#define AMD_DR_ALL (AMD_DR_Bx) ++#define AMD_FAM10_ALL (AMD_DR_ALL | AMD_RB_C2 | AMD_HY_D0 | AMD_DA_C3 | AMD_DA_C2 | AMD_RB_C3 | AMD_HY_D1 | AMD_PH_E0) ++#define AMD_FAM10_LT_D (AMD_FAM10_ALL & ~(AMD_HY_D0)) ++#define AMD_FAM10_GT_B0 (AMD_FAM10_ALL & ~(AMD_DR_B0)) ++#define AMD_FAM10_REV_D (AMD_HY_D0 | AMD_HY_D1) ++#define AMD_DA_Cx (AMD_DA_C2 | AMD_DA_C3) ++#define AMD_FAM10_C3 (AMD_RB_C3 | AMD_DA_C3) ++#define AMD_DRBH_Cx (AMD_DR_Cx | AMD_HY_D0 ) ++#define AMD_DRBA23_RBC2 (AMD_DR_BA | AMD_DR_B2 | AMD_DR_B3 | AMD_RB_C2 ) + #define AMD_DR_DAC2_OR_C3 (AMD_DA_C2 | AMD_DA_C3 | AMD_RB_C3) +-#define AMD_FAM15_ALL (AMD_OR_B2 | AMD_OR_C0) ++#define AMD_FAM15_ALL (AMD_OR_B2 | AMD_OR_C0) + + /* + * Public Platforms - USE THESE VERSIONS TO MAKE COMPARE WITH CPUPLATFORMTYPE RETURN VALUE +@@ -91,9 +93,9 @@ + #define AMD_PTYPE_MC 0x020 /* Multi Core (>2) */ + #define AMD_PTYPE_UMA 0x040 /* UMA required */ + +- /* +- * Groups - Create as many as you wish, from the above public values +- */ ++/* ++ * Groups - Create as many as you wish, from the above public values ++ */ + #define AMD_PTYPE_ALL 0xFFFFFFFF /* A mask for all */ + + +@@ -102,11 +104,11 @@ + */ + #define HTPHY_LINKTYPE_HT3 0x00000001 + #define HTPHY_LINKTYPE_HT1 0x00000002 +-#define HTPHY_LINKTYPE_COHERENT 0x00000004 ++#define HTPHY_LINKTYPE_COHERENT 0x00000004 + #define HTPHY_LINKTYPE_NONCOHERENT 0x00000008 + #define HTPHY_LINKTYPE_CONNECTED (HTPHY_LINKTYPE_COHERENT | HTPHY_LINKTYPE_NONCOHERENT) + #define HTPHY_LINKTYPE_GANGED 0x00000010 +-#define HTPHY_LINKTYPE_UNGANGED 0x00000020 ++#define HTPHY_LINKTYPE_UNGANGED 0x00000020 + #define HTPHY_LINKTYPE_ALL 0x7FFFFFFF + + +@@ -114,7 +116,7 @@ + * CPU HT PHY REGISTERS, FIELDS, AND MASKS + */ + #define HTPHY_OFFSET_MASK 0xE00001FF +-#define HTPHY_WRITE_CMD 0x40000000 ++#define HTPHY_WRITE_CMD 0x40000000 + #define HTPHY_IS_COMPLETE_MASK 0x80000000 + #define HTPHY_DIRECT_MAP 0x20000000 + #define HTPHY_DIRECT_OFFSET_MASK 0xE000FFFF +@@ -162,4 +164,4 @@ + #define AMD_PKGTYPE_S1gX 2 + #define AMD_PKGTYPE_G34 3 + #define AMD_PKGTYPE_ASB2 4 +-#define AMD_PKGTYPE_C32 5 ++#define AMD_PKGTYPE_C32 5 +\ No newline at end of file +diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c +index 2798506..4044c36 100644 +--- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c ++++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c +@@ -1197,6 +1197,7 @@ static void set_up_cc6_storage_fam15(struct MCTStatStruc *pMCTstat, + int8_t max_range; + uint8_t max_node; + uint64_t max_range_limit; ++ uint8_t byte; + uint32_t dword; + uint32_t dword2; + uint64_t qword; +@@ -1216,7 +1217,8 @@ static void set_up_cc6_storage_fam15(struct MCTStatStruc *pMCTstat, + + dword = Get_NB32(pDCTstat->dev_map, 0x44 + (range * 0x8)); + dword2 = Get_NB32(pDCTstat->dev_map, 0x144 + (range * 0x8)); +- qword = ((((uint64_t)dword) >> 16) & 0xffff) << 24; ++ qword = 0xffffff; ++ qword |= ((((uint64_t)dword) >> 16) & 0xffff) << 24; + qword |= (((uint64_t)dword2) & 0xff) << 40; + + if (qword > max_range_limit) { +@@ -1226,26 +1228,35 @@ static void set_up_cc6_storage_fam15(struct MCTStatStruc *pMCTstat, + } + } + +- if (pDCTstat->Node_ID == max_node) { +- if (max_range >= 0) { +- if (interleaved) +- /* Move upper limit down by 16M * the number of nodes */ +- max_range_limit -= (0x1000000 * num_nodes); +- else +- /* Move upper limit down by 16M */ +- max_range_limit -= 0x1000000; +- +- /* Store modified range */ +- dword = Get_NB32(pDCTstat->dev_map, 0x44 + (range * 0x8)); +- dword &= ~(0xffff << 16); /* DramLimit[39:24] = max_range_limit[39:24] */ +- dword |= (max_range_limit >> 24) & 0xffff; +- Set_NB32(pDCTstat->dev_map, 0x44 + (range * 0x8), dword); +- +- dword = Get_NB32(pDCTstat->dev_map, 0x144 + (range * 0x8)); +- dword &= ~(0xffff << 16); /* DramLimit[47:40] = max_range_limit[47:40] */ +- dword |= (max_range_limit >> 40) & 0xff; +- Set_NB32(pDCTstat->dev_map, 0x144 + (range * 0x8), dword); +- } ++ if (max_range >= 0) { ++ if (interleaved) ++ /* Move upper limit down by 16M * the number of nodes */ ++ max_range_limit -= (0x1000000 * num_nodes); ++ else ++ /* Move upper limit down by 16M */ ++ max_range_limit -= 0x1000000; ++ ++ /* Disable the range */ ++ dword = Get_NB32(pDCTstat->dev_map, 0x40 + (max_range * 0x8)); ++ byte = dword & 0x3; ++ dword &= ~(0x3); ++ Set_NB32(pDCTstat->dev_map, 0x40 + (max_range * 0x8), dword); ++ ++ /* Store modified range */ ++ dword = Get_NB32(pDCTstat->dev_map, 0x44 + (max_range * 0x8)); ++ dword &= ~(0xffff << 16); /* DramLimit[39:24] = max_range_limit[39:24] */ ++ dword |= ((max_range_limit >> 24) & 0xffff) << 16; ++ Set_NB32(pDCTstat->dev_map, 0x44 + (max_range * 0x8), dword); ++ ++ dword = Get_NB32(pDCTstat->dev_map, 0x144 + (max_range * 0x8)); ++ dword &= ~0xff; /* DramLimit[47:40] = max_range_limit[47:40] */ ++ dword |= (max_range_limit >> 40) & 0xff; ++ Set_NB32(pDCTstat->dev_map, 0x144 + (max_range * 0x8), dword); ++ ++ /* Reenable the range */ ++ dword = Get_NB32(pDCTstat->dev_map, 0x40 + (max_range * 0x8)); ++ dword |= byte; ++ Set_NB32(pDCTstat->dev_map, 0x40 + (max_range * 0x8), dword); + } + + /* Determine save state destination node */ +@@ -1531,8 +1542,8 @@ restartinit: + pDCTstat = pDCTstatA + Node; + + if (pDCTstat->NodePresent) { +- lock_dram_config(pMCTstat, pDCTstat); + set_cc6_save_enable(pMCTstat, pDCTstat, 1); ++ lock_dram_config(pMCTstat, pDCTstat); + } + } + } +@@ -5110,7 +5121,7 @@ static void mct_HTMemMapExt(struct MCTStatStruc *pMCTstat, + /* get base/limit from Node0 */ + reg = 0x40 + (Node << 3); /* Node0/Dram Base 0 */ + val = Get_NB32(dev, reg); +- Drambase = val >> ( 16 + 3); ++ Drambase = val >> (16 + 3); + + reg = 0x44 + (Node << 3); /* Node0/Dram Base 0 */ + val = Get_NB32(dev, reg); +diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c +index 11f1b2c..3a9fecc 100644 +--- a/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c ++++ b/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c +@@ -159,6 +159,14 @@ u8 ECCInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA) + if (MemClrECC) { + MCTMemClrSync_D(pMCTstat, pDCTstatA); + } ++ ++ if (pDCTstat->LogicalCPUID & (AMD_DR_GT_D0 | AMD_FAM15_ALL)) { ++ /* Set up message triggered C1E */ ++ val = pci_read_config32(pDCTstat->dev_nbmisc, 0xd4); ++ val &= ~(0x1 << 15); /* StutterScrubEn = DRAM scrub enabled */ ++ val |= (mctGet_NVbits(NV_DramBKScrub)?1:0) << 15; ++ pci_write_config32(pDCTstat->dev_nbmisc, 0xd4, val); ++ } + } /* if Node present */ + } + +diff --git a/src/southbridge/amd/sb700/early_setup.c b/src/southbridge/amd/sb700/early_setup.c +index a6849b0..fd3b099 100644 +--- a/src/southbridge/amd/sb700/early_setup.c ++++ b/src/southbridge/amd/sb700/early_setup.c +@@ -22,6 +22,7 @@ + #define _SB700_EARLY_SETUP_C_ + + #include <stdint.h> ++#include <option.h> + #include <arch/acpi.h> + #include <arch/cpu.h> + #include <arch/io.h> +@@ -271,10 +272,6 @@ void enable_fid_change_on_sb(u32 sbbusn, u32 sbdn) + byte &= ~(1<<6); + pmio_write(0x8d, byte); + +- byte = pmio_read(0x61); +- byte &= ~0x04; +- pmio_write(0x61, byte); +- + byte = pmio_read(0x42); + byte &= ~0x04; + pmio_write(0x42, byte); +@@ -560,6 +557,13 @@ static void sb700_devices_por_init(void) + static void sb700_pmio_por_init(void) + { + u8 byte; ++ uint8_t enable_c_states; ++ ++ enable_c_states = 0; ++#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES) ++ if (get_option(&byte, "cpu_c_states") == CB_SUCCESS) ++ enable_c_states = !!byte; ++#endif + + printk(BIOS_INFO, "sb700_pmio_por_init()\n"); + /* K8KbRstEn, KB_RST# control for K8 system. */ +@@ -621,6 +625,14 @@ static void sb700_pmio_por_init(void) + byte |= 1 << 0; + pmio_write(0xB2, byte); + ++ /* Set up IOAPIC and BM_STS monitoring */ ++ byte = pmio_read(0x61); ++ if (enable_c_states) ++ byte |= 0x4; ++ else ++ byte &= ~0x04; ++ pmio_write(0x61, byte); ++ + // FIXME: Enabling this causes boot to hang while initializing processors. + // /* Enable automatic C1e state switch */ + // byte = pmio_read(0xc9); +diff --git a/src/southbridge/amd/sb700/fadt.c b/src/southbridge/amd/sb700/fadt.c +index 96996a3..6b1924f 100644 +--- a/src/southbridge/amd/sb700/fadt.c ++++ b/src/southbridge/amd/sb700/fadt.c +@@ -2,6 +2,7 @@ + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Advanced Micro Devices, Inc. ++ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -26,6 +27,7 @@ + #include <arch/acpi.h> + #include <arch/io.h> + #include <device/device.h> ++#include <cpu/amd/powernow.h> + #include "sb700.h" + + void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) +@@ -156,5 +158,7 @@ void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) + fadt->x_gpe1_blk.addrl = 0; + fadt->x_gpe1_blk.addrh = 0x0; + ++ amd_powernow_update_fadt(fadt); ++ + header->checksum = acpi_checksum((void *)fadt, sizeof(acpi_fadt_t)); + } +diff --git a/src/southbridge/amd/sb700/sb700.h b/src/southbridge/amd/sb700/sb700.h +index b477091..941a4fd 100644 +--- a/src/southbridge/amd/sb700/sb700.h ++++ b/src/southbridge/amd/sb700/sb700.h +@@ -36,10 +36,11 @@ + + #define ACPI_PM_EVT_BLK (SB700_ACPI_IO_BASE + 0x00) /* 4 bytes */ + #define ACPI_PM1_CNT_BLK (SB700_ACPI_IO_BASE + 0x04) /* 2 bytes */ +-#define ACPI_PMA_CNT_BLK (SB700_ACPI_IO_BASE + 0x0E) /* 1 byte */ +-#define ACPI_PM_TMR_BLK (SB700_ACPI_IO_BASE + 0x18) /* 4 bytes */ +-#define ACPI_GPE0_BLK (SB700_ACPI_IO_BASE + 0x10) /* 8 bytes */ ++#define ACPI_PMA_CNT_BLK (SB700_ACPI_IO_BASE + 0x16) /* 1 byte */ ++#define ACPI_PM_TMR_BLK (SB700_ACPI_IO_BASE + 0x20) /* 4 bytes */ ++#define ACPI_GPE0_BLK (SB700_ACPI_IO_BASE + 0x18) /* 8 bytes */ + #define ACPI_CPU_CONTROL (SB700_ACPI_IO_BASE + 0x08) /* 6 bytes */ ++#define ACPI_CPU_P_LVL2 (ACPI_CPU_CONTROL + 0x4) /* 1 byte */ + + extern void pm_iowrite(u8 reg, u8 value); + extern u8 pm_ioread(u8 reg); +diff --git a/src/southbridge/amd/sb700/sm.c b/src/southbridge/amd/sb700/sm.c +index a4b78d0..81e3046 100644 +--- a/src/southbridge/amd/sb700/sm.c ++++ b/src/southbridge/amd/sb700/sm.c +@@ -114,7 +114,10 @@ static void sm_init(device_t dev) + pci_write_config8(dev, 0x41, byte); + + byte = pm_ioread(0x61); +- byte |= 1 << 1; /* Set to enable NB/SB handshake during IOAPIC interrupt for AMD K8/K7 */ ++ if (IS_ENABLED(CONFIG_CPU_AMD_MODEL_10XXX)) ++ byte &= ~(1 << 1); /* Clear for non-K8 CPUs */ ++ else ++ byte |= 1 << 1; /* Set to enable NB/SB handshake during IOAPIC interrupt for AMD K8/K7 */ + pm_iowrite(0x61, byte); + + /* disable SMI */ +diff --git a/src/southbridge/amd/sb800/fadt.c b/src/southbridge/amd/sb800/fadt.c +index fea98f9..5250e20 100644 +--- a/src/southbridge/amd/sb800/fadt.c ++++ b/src/southbridge/amd/sb800/fadt.c +@@ -26,6 +26,7 @@ + #include <arch/acpi.h> + #include <arch/io.h> + #include <device/device.h> ++#include <cpu/amd/powernow.h> + #include "sb800.h" + + void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) +@@ -156,5 +157,7 @@ void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) + fadt->x_gpe1_blk.addrl = 0; + fadt->x_gpe1_blk.addrh = 0x0; + ++ amd_powernow_update_fadt(fadt); ++ + header->checksum = acpi_checksum((void *)fadt, sizeof(acpi_fadt_t)); + } +diff --git a/src/southbridge/amd/sb800/sb800.h b/src/southbridge/amd/sb800/sb800.h +index 9049182..3e3f077 100644 +--- a/src/southbridge/amd/sb800/sb800.h ++++ b/src/southbridge/amd/sb800/sb800.h +@@ -2,6 +2,7 @@ + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Advanced Micro Devices, Inc. ++ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -35,10 +36,11 @@ + + #define ACPI_PM_EVT_BLK (SB800_ACPI_IO_BASE + 0x00) /* 4 bytes */ + #define ACPI_PM1_CNT_BLK (SB800_ACPI_IO_BASE + 0x04) /* 2 bytes */ +-#define ACPI_PMA_CNT_BLK (SB800_ACPI_IO_BASE + 0x0F) /* 1 byte */ +-#define ACPI_PM_TMR_BLK (SB800_ACPI_IO_BASE + 0x18) /* 4 bytes */ +-#define ACPI_GPE0_BLK (SB800_ACPI_IO_BASE + 0x10) /* 8 bytes */ ++#define ACPI_PMA_CNT_BLK (SB800_ACPI_IO_BASE + 0x17) /* 1 byte */ ++#define ACPI_PM_TMR_BLK (SB800_ACPI_IO_BASE + 0x20) /* 4 bytes */ ++#define ACPI_GPE0_BLK (SB800_ACPI_IO_BASE + 0x18) /* 8 bytes */ + #define ACPI_CPU_CONTROL (SB800_ACPI_IO_BASE + 0x08) /* 6 bytes */ ++#define ACPI_CPU_P_LVL2 (ACPI_CPU_CONTROL + 0x4) /* 1 byte */ + + void pm_iowrite(u8 reg, u8 value); + u8 pm_ioread(u8 reg); +-- +1.9.1 + |