CPU: Add basic support for Nominal Configurable TDP

Ivybridge B0+ CPUs are capable of supporting multiple TDP levels.
This complicates the default case because now the registers that
were reporting max non-turbo ratio are reporting that value for
the highest possible TDP level.

For now this change just forces everything to use the Nominal TDP
values instead of the higher (or lower) levels.

- When building P-state tables, determine the P[1] (max non turbo)
ratio based on the Nominal ratio if available.
- Set the turbo activation ratio to the Nominal max ratio.
- Mirror the power level settings in new MCHBAR register after
they are written, which happens after BIOS_RESET_CPL is set.
- Set the current ratio to Nominal ratio at boot.

1) Verify that P-state table is generated properly with
P[0]=1801MHz (ratio 0x1C) and P[1]=1800MHz (ratio 0x12)

PSS: 1801MHz power 17000 control 0x1c00 status 0x1c00
PSS: 1800MHz power 17000 control 0x1200 status 0x1200

2) Verify power limits in MCHBAR match PKG_POWER_LIMIT:

> rdmsr 0 0x610
0x800080aa00dc8088
> mmio_read32 0xfed159a4
0x000080aa
> mmio_read32 0xfed159a0
0x00dc8088

3) Verify turbo activation ratio is set to nominal ratio:

> rdmsr 0 0x64c
0x0000000000000012

4) Check that proper ratio was set at boot on one core only:

> grep 'frequency set to' /sys/firmware/log
model_x06ax: frequency set to 1800
model_x06ax: frequency set to 1800
model_x06ax: frequency set to 1800
model_x06ax: frequency set to 1800

Change-Id: I592e60a7740f31b140986a8269dca91b4adbb270
Signed-off-by: Duncan Laurie <dlaurie@chromium.org>
Reviewed-on: http://review.coreboot.org/1304
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
diff --git a/src/cpu/intel/model_206ax/model_206ax_init.c b/src/cpu/intel/model_206ax/model_206ax_init.c
index 87bc585..0958fe3 100644
--- a/src/cpu/intel/model_206ax/model_206ax_init.c
+++ b/src/cpu/intel/model_206ax/model_206ax_init.c
@@ -179,6 +179,19 @@
 	[0x11] = 128,
 };
 
+int cpu_config_tdp_levels(void)
+{
+	msr_t platform_info;
+
+	/* Minimum CPU revision */
+	if (cpuid_eax(1) < IVB_CONFIG_TDP_MIN_CPUID)
+		return 0;
+
+	/* Bits 34:33 indicate how many levels supported */
+	platform_info = rdmsr(MSR_PLATFORM_INFO);
+	return (platform_info.hi >> 1) & 3;
+}
+
 /*
  * Configure processor power limits if possible
  * This must be done AFTER set of BIOS_RESET_CPL
@@ -235,6 +248,14 @@
 	/* Power limit 2 time is only programmable on SNB EP/EX */
 
 	wrmsr(MSR_PKG_POWER_LIMIT, limit);
+
+	/* Use nominal TDP values for CPUs with configurable TDP */
+	if (cpu_config_tdp_levels()) {
+		msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
+		limit.hi = 0;
+		limit.lo = msr.lo & 0xff;
+		wrmsr(MSR_TURBO_ACTIVATION_RATIO, limit);
+	}
 }
 
 static void configure_c_states(void)
@@ -340,16 +361,24 @@
 
 static void set_max_ratio(void)
 {
-	msr_t msr;
+	msr_t msr, perf_ctl;
 
-	/* Platform Info bits 15:8 give max ratio */
-	msr = rdmsr(MSR_PLATFORM_INFO);
-	msr.hi = 0;
-	msr.lo &= 0xff00;
-	wrmsr(IA32_PERF_CTL, msr);
+	perf_ctl.hi = 0;
+
+	/* Check for configurable TDP option */
+	if (cpu_config_tdp_levels()) {
+		/* Set to nominal TDP ratio */
+		msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
+		perf_ctl.lo = (msr.lo & 0xff) << 8;
+	} else {
+		/* Platform Info bits 15:8 give max ratio */
+		msr = rdmsr(MSR_PLATFORM_INFO);
+		perf_ctl.lo = msr.lo & 0xff00;
+	}
+	wrmsr(IA32_PERF_CTL, perf_ctl);
 
 	printk(BIOS_DEBUG, "model_x06ax: frequency set to %d\n",
-	       ((msr.lo >> 8) & 0xff) * 100);
+	       ((perf_ctl.lo >> 8) & 0xff) * SANDYBRIDGE_BCLK);
 }
 
 static void set_energy_perf_bias(u8 policy)