From ce62350d8f5a619c9ce754caeb1e33224e0cce56 Mon Sep 17 00:00:00 2001 From: Xavi Drudis Ferran Date: Mon, 28 Feb 2011 03:19:17 +0000 Subject: [PATCH] Improving BKDG implementation of P-states, CPU and northbridge frequency and voltage handling for Fam 10 in SVI mode. Add to init_fidvid_stage2 some step mentioned in BKDG 2.4.2.7 that was missing . Some lines are dead code now, but may handy if one day we support revison E CPUs. Signed-off-by: Xavi Drudis Ferran Acked-by: Marc Jones git-svn-id: svn://svn.coreboot.org/coreboot/trunk@6404 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- src/cpu/amd/model_10xxx/fidvid.c | 53 ++++++++++++++++++++++++++++ src/northbridge/amd/amdht/AsPsDefs.h | 3 ++ 2 files changed, 56 insertions(+) diff --git a/src/cpu/amd/model_10xxx/fidvid.c b/src/cpu/amd/model_10xxx/fidvid.c index 53a5f18751..d621f8ddf2 100644 --- a/src/cpu/amd/model_10xxx/fidvid.c +++ b/src/cpu/amd/model_10xxx/fidvid.c @@ -85,6 +85,58 @@ static void enableNbPState1( device_t dev ) { } } +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 + + u32 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); + + } + } +} + static void setVSRamp(device_t dev) { /* BKDG r31116 2010-04-22 2.4.1.7 step b F3xD8[VSRampTime] * If this field accepts 8 values between 10 and 500 us why @@ -819,6 +871,7 @@ static void init_fidvid_stage2(u32 apicid, u32 nodeid) dtemp |= PLLLOCK_DFT_L; pci_write_config32(dev, 0xA0, dtemp); + dualPlaneOnly(dev); enableNbPState1(dev); finalPstateChange(); diff --git a/src/northbridge/amd/amdht/AsPsDefs.h b/src/northbridge/amd/amdht/AsPsDefs.h index 13e6548873..ef2e75e4b6 100644 --- a/src/northbridge/amd/amdht/AsPsDefs.h +++ b/src/northbridge/amd/amdht/AsPsDefs.h @@ -191,6 +191,7 @@ #define NB_SYN_PTR_ADJ_MASK (0x7 << NB_SYN_PTR_ADJ_POS) /* NbsynPtrAdj bit mask */ #define PRCT_INFO 0x1fc /* Product Info Register */ +#define DUAL_PLANE_ONLY_MASK 0x80000000 /* F3x1FC[DualPlaneOnly] */ #define UNI_NB_FID_BIT 2 /* UniNbFid bit position */ #define UNI_NB_VID_BIT 7 /* UniNbVid bit position */ #define SPLT_NB_FID_OFFSET 14 /* SpltNbFidOffset value bit position */ @@ -199,6 +200,8 @@ #define NB_VID_UPDATE_ALL 0x02 /* F3x1FC[NbVidUpdatedAll] bit mask */ #define C_FID_DID_M_OFF 0xfffffe00 /* mask off Core FID & DID */ +#define CPB_MASK 0x00000020 /* core performance + boost. CPUID Fn8000 0007 edx */ #define PW_CTL_MISC 0x0a0 /* Power Control Miscellaneous Register */ #define COF_VID_PROG_BIT 0x80000000 /* CofVidProg bit. 0= unfused part */ #define DUAL_VDD_BIT 0x40000000 /* DualVdd bit. */