From 8f0d565329ddc702412d6941a5a0fea7c81e73e8 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Mon, 8 Jun 2015 19:35:06 -0500 Subject: [PATCH 047/143] cpu/amd: Add CC6 support Change-Id: I44ce157cda97fb85f3e8f3d7262d4712b5410670 Signed-off-by: Timothy Pearson --- 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 | 81 ++++++++++ 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 | 81 +++++++++- 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 | 5 + src/southbridge/amd/sb700/sb700.h | 7 +- src/southbridge/amd/sb700/sm.c | 5 +- src/southbridge/amd/sb800/fadt.c | 4 + src/southbridge/amd/sb800/sb800.h | 8 +- 20 files changed, 544 insertions(+), 201 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 , Raptor Engineering * Copyright (C) 2009 Rudolf Marek * * 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 #include @@ -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 + * Copyright (C) 2015 Timothy Pearson , 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 e8e0818..0e7d299 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..061bba2 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 #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); @@ -874,6 +882,7 @@ void cpuSetAMDMSR(uint8_t node_id) u8 i; u32 platform; uint64_t revision; + uint8_t enable_c_states; printk(BIOS_DEBUG, "cpuSetAMDMSR "); @@ -936,6 +945,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"); } @@ -950,6 +997,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 +1056,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 #include +#include #include #include #include @@ -34,21 +35,29 @@ #include #include +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 + * Copyright (C) 2015 Timothy Pearson , 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..7fa9f12 100644 --- a/src/northbridge/amd/amdfam10/link_control.c +++ b/src/northbridge/amd/amdfam10/link_control.c @@ -49,15 +49,94 @@ static inline uint8_t is_fam15h(void) static void nb_control_init(struct device *dev) { + 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) + uint8_t nvram; + + 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"); @@ -83,4 +162,4 @@ static const struct pci_driver mcf4_driver_fam15 __pci_driver = { .ops = &mcf4_ops, .vendor = PCI_VENDOR_ID_AMD, .device = 0x1604, -}; \ No newline at end of file +}; diff --git a/src/northbridge/amd/amdfam10/northbridge.c b/src/northbridge/amd/amdfam10/northbridge.c index e5612fa..9fe0ccb 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 , 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 +#include #include #include #include @@ -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..e860016 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 , 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 #include #include +#include #include "sb700.h" void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) @@ -156,5 +158,8 @@ 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; + if (IS_ENABLED(CONFIG_CPU_AMD_MODEL_10XXX)) + 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 71253b5..5bd49c5 100644 --- a/src/southbridge/amd/sb700/sm.c +++ b/src/southbridge/amd/sb700/sm.c @@ -117,7 +117,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..30b4496 100644 --- a/src/southbridge/amd/sb800/fadt.c +++ b/src/southbridge/amd/sb800/fadt.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "sb800.h" void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) @@ -156,5 +157,8 @@ 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; + if (IS_ENABLED(CONFIG_CPU_AMD_MODEL_10XXX)) + 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 , 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.7.9.5