Improving BKDG implementation of P-states,
authorXavi Drudis Ferran <xdrudis@tinet.cat>
Mon, 28 Feb 2011 03:32:23 +0000 (03:32 +0000)
committerMarc Jones <marc.jones@amd.com>
Mon, 28 Feb 2011 03:32:23 +0000 (03:32 +0000)
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

src/cpu/amd/model_10xxx/fidvid.c
src/northbridge/amd/amdht/AsPsDefs.h

index b1bcac577a3617557e47ab2618fe7c37c9d12bc5..962b8ca17801e7050b54a4d3e1790b2f54b79fa4 100644 (file)
@@ -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
index eefedb63ee475bfeedd9348f81241fb5e04210c5..dd59496c49a14f7923231209d0dea6278399067e 100644 (file)
@@ -25,7 +25,7 @@
 #define APIC_BAR_BP 0x100              /* APIC_BAR BSP bit */
 
 #define PS_LIM_REG 0xC0010061          /* P-state Current Limit Register */
-#define PS_CUR_LIM_SHFT 4              /* P-state Current Limit shift position */
+#define PS_MAX_VAL_SHFT 4              /* P-state Maximum Value shift position */
 
 #define PS_CTL_REG 0xC0010062          /* P-state Control Register */
 #define PS_CMD_MASK_OFF 0xfffffff8     /* P-state Control Register CMD Mask OFF */