diff options
author | Xavi Drudis Ferran <xdrudis@tinet.cat> | 2011-02-28 03:32:23 +0000 |
---|---|---|
committer | Marc Jones <marc.jones@amd.com> | 2011-02-28 03:32:23 +0000 |
commit | 82b241a2b5e38046a519673264c47c64d4c85728 (patch) | |
tree | e66acb13315f9ed2617822cc333c96e75a6f03f8 /src/cpu/amd | |
parent | 5bcedee0f88fa6390d84f2641dc5b3e109cf6ea3 (diff) |
Improving BKDG implementation of P-states,
CPU and northbridge frequency and voltage
handling for Fam 10 in SVI mode.
Well, I understand it better like this, but maybe
it's only me, part of the changes are paranoic, and
the only effective change is for a factor depending on
mobile or not that I can't test.
Signed-off-by: Xavi Drudis Ferran <xdrudis@tinet.cat>
Acked-by: Marc Jones <marcj303@gmail.com>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@6406 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/cpu/amd')
-rw-r--r-- | src/cpu/amd/model_10xxx/fidvid.c | 60 |
1 files changed, 39 insertions, 21 deletions
diff --git a/src/cpu/amd/model_10xxx/fidvid.c b/src/cpu/amd/model_10xxx/fidvid.c index b1bcac577a..962b8ca178 100644 --- a/src/cpu/amd/model_10xxx/fidvid.c +++ b/src/cpu/amd/model_10xxx/fidvid.c @@ -155,6 +155,18 @@ static void dualPlaneOnly( device_t dev ) { } } +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; +} + 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 @@ -181,12 +193,14 @@ static void recalculateVsSlamTimeSettingOnCorePre(device_t dev) /* This function calculates the VsSlamTime using the range of possible * voltages instead of a hardcoded 200us. - * Note:This function is called from setFidVidRegs and setUserPs after - * programming a custom Pstate. + * Note: his function is called only from prep_fid_change, + * and that from init_cpus.c finalize_node_setup() + * (after set AMD MSRs and init ht ) */ + /* BKDG r31116 2010-04-22 2.4.1.7 step b F3xD8[VSSlamTime] */ /* Calculate Slam Time - * Vslam = 0.4us/mV * Vp0 - (lowest out of Vpmin or Valt) + * Vslam = (mobileCPU?0.2:0.4)us/mV * (Vp0 - (lowest out of Vpmin or Valt)) mV * In our case, we will scale the values by 100 to avoid * decimals. */ @@ -200,8 +214,17 @@ static void recalculateVsSlamTimeSettingOnCorePre(device_t dev) pviModeFlag = 0; /* Get P0's voltage */ + /* MSRC001_00[68:64] are not programmed yet when called from + prep_fid_change, one might use F4x1[F0:E0] instead, but + theoretically MSRC001_00[68:64] are equal to them after + reset. */ msr = rdmsr(0xC0010064); highVoltageVid = (u8) ((msr.lo >> PS_CPU_VID_SHFT) & 0x7F); + if (!(msr.hi & 0x80000000)) { + printk(BIOS_ERR,"P-state info in MSRC001_0064 is invalid !!!\n"); + highVoltageVid = (u8) ((pci_read_config32(dev, 0x1E0) + >> PS_CPU_VID_SHFT) & 0x7F); + } /* If SVI, we only care about CPU VID. * If PVI, determine the higher voltage b/t NB and CPU @@ -212,17 +235,23 @@ static void recalculateVsSlamTimeSettingOnCorePre(device_t dev) highVoltageVid = bValue; } - /* Get Pmin's index */ + /* Get PSmax's index */ msr = rdmsr(0xC0010061); - bValue = (u8) ((msr.lo >> PS_CUR_LIM_SHFT) & BIT_MASK_3); - - /* Get Pmin's VID */ + bValue = (u8) ((msr.lo >> PS_MAX_VAL_SHFT) & BIT_MASK_3); + + /* Get PSmax's VID */ msr = rdmsr(0xC0010064 + bValue); lowVoltageVid = (u8) ((msr.lo >> PS_CPU_VID_SHFT) & 0x7F); + if (!(msr.hi & 0x80000000)) { + printk(BIOS_ERR,"P-state info in MSR%8x is invalid !!!\n",0xC0010064 + bValue); + lowVoltageVid = (u8) ((pci_read_config32(dev, 0x1E0+(bValue*4)) + >> PS_CPU_VID_SHFT) & 0x7F); + } /* If SVI, we only care about CPU VID. * If PVI, determine the higher voltage b/t NB and CPU - */ + * BKDG 2.4.1.7 (a) + */ if (pviModeFlag) { bValue = (u8) ((msr.lo >> PS_NB_VID_SHFT) & 0x7F); if (lowVoltageVid > bValue) @@ -237,20 +266,9 @@ static void recalculateVsSlamTimeSettingOnCorePre(device_t dev) if (lowVoltageVid < bValue) lowVoltageVid = bValue; - /* If Vids are 7Dh - 7Fh, force 7Ch to keep calculations linear */ - if (lowVoltageVid > 0x7C) { - lowVoltageVid = 0x7C; - if (highVoltageVid > 0x7C) - highVoltageVid = 0x7C; - } + u8 mobileFlag = get_platform_type() & AMD_PTYPE_MOB; + minimumSlamTime = (mobileFlag?2:4) * (vidTo100uV(highVoltageVid) - vidTo100uV(lowVoltageVid)); /* * 0.01 us */ - bValue = (u8) (lowVoltageVid - highVoltageVid); - - /* Each Vid increment is 12.5 mV. The minimum slam time is: - * vidCodeDelta * 12.5mV * 0.4us/mV - * Scale by 100 to avoid decimals. - */ - minimumSlamTime = bValue * (125 * 4); /* Now round up to nearest register setting. * Note that if we don't find a value, we |