[coreboot] Patch set updated for coreboot: c626561 Fixes several issues with amd k8 SSDT P-state generation

Oskar Enoksson (enok@lysator.liu.se) gerrit at coreboot.org
Mon Oct 10 14:52:30 CEST 2011


Oskar Enoksson (enok at lysator.liu.se) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/239

-gerrit

commit c626561a2308efad8b07920932248d15f819e314
Author: Oskar Enoksson <enok at lysator.liu.se>
Date:   Thu Oct 6 18:43:43 2011 +0200

    Fixes several issues with amd k8 SSDT P-state generation
    
    First issue fixed:
    For multi-socket CPU the current implementation emitted
    Processor objects for cores in the first CPU only. This
    commit fixes the bug by really emitting one Processor
    object for each core. However, the unlikely case of mixed
    CPU models is still not handled correctly.
    
    Second issue fixed:
    One loop was wrong in case a processor in the table declares
    no P-states at all. The rewritten loop is safe. Some possibly
    dangerous array lengths were also fixed.
    
    Third issue: on MP-boards the recommended ramp-voltage (RVO) is 0mV
    according to the BKDG. The current implementation always set it
    to 25mV. This commit selects 0 or 25mV depending on CONFIG_MAX_PHYSICAL_CPUS.
    
    Fourth issue: If a processor without PowerNow! support was inserted in a
    system with coreboot configured with SET_FIDVID then the boot process hanged
    mysteriously and very early. Apparently because init_fidvid_ap tampers with
    non-existing registers. This commit fixes the bug by bailing out
    from init_fidvid_ap if PowerNow! capability is missing.
    
    Signed-off-by: Oskar Enoksson <enok at lysator.liu.se>
    Change-Id: I61f6e2210b84ccba33a36c5efc866447b7134417
---
 src/cpu/amd/model_fxx/fidvid.c        |    4 ++
 src/cpu/amd/model_fxx/powernow_acpi.c |   86 +++++++++++++++++++++++++--------
 2 files changed, 69 insertions(+), 21 deletions(-)

diff --git a/src/cpu/amd/model_fxx/fidvid.c b/src/cpu/amd/model_fxx/fidvid.c
index bbafde6..62a25d6 100644
--- a/src/cpu/amd/model_fxx/fidvid.c
+++ b/src/cpu/amd/model_fxx/fidvid.c
@@ -347,6 +347,10 @@ static void init_fidvid_ap(unsigned bsp_apicid, unsigned apicid)
 	u32 fid_max;
 	int loop;
 
+	if((cpuid_edx(0x80000007)&0x06)!=0x06) {
+		return; // FID/VID change not supported
+	}
+
 	msr = rdmsr(0xc0010042);
 	fid_max = ((msr.lo >> 16) & 0x3f);	/* max fid */
 #if FX_SUPPORT
diff --git a/src/cpu/amd/model_fxx/powernow_acpi.c b/src/cpu/amd/model_fxx/powernow_acpi.c
index bbcf013..b39eee1 100644
--- a/src/cpu/amd/model_fxx/powernow_acpi.c
+++ b/src/cpu/amd/model_fxx/powernow_acpi.c
@@ -586,15 +586,26 @@ static int pstates_algorithm(u32 pcontrol_blk, u8 plen, u8 onlyBSP)
 	u8 cmp_cap;
 	struct cpuentry *data = NULL;
 	uint32_t control;
-	int i = 0, index, len = 0, Pstate_num = 0;
+	int i = 0, index = 0, len = 0, Pstate_num = 0, dev = 0;
 	msr_t msr;
-	u8 Pstate_fid[10];
-	u16 Pstate_feq[10];
-	u8 Pstate_vid[10];
-	u32 Pstate_power[10];
+	u8 Pstate_fid[MAXP+1];
+	u16 Pstate_feq[MAXP+1];
+	u8 Pstate_vid[MAXP+1];
+	u32 Pstate_power[MAXP+1];
 	u8 Max_fid, Start_fid, Start_vid, Max_vid;
-	struct cpuid_result cpuid1 = cpuid(0x80000001);
+	struct cpuid_result cpuid1;
+
+	/* See if the CPUID(0x80000007) returned EDX[2:1]==11b */
+	cpuid1 = cpuid(0x80000007);
+	if((cpuid1.edx & 0x6)!=0x6) {
+		printk(BIOS_INFO, "Processor not capable of performing P-state transitions\n");
+		return 0;
+	}
+
+	cpuid1 = cpuid(0x80000001);
 
+	// Because I don't know how to read msr registers from
+	// other CPU's I assume they all have the same SYSCONF values
 	msr = rdmsr(0xc0010042);
 	Max_fid = (msr.lo & 0x3F0000) >> 16;
 	Max_vid = (msr.hi & 0x3F0000) >> 16;
@@ -620,24 +631,50 @@ static int pstates_algorithm(u32 pcontrol_blk, u8 plen, u8 onlyBSP)
 		return 0;
 	}
 
-	/* IRT 80us, PLL_LOCK_TIME 2us, MVS 25mv, VST 100us */
-	control = (3 << 30) | (2 << 20) | (0 << 18) | (5 << 11) | (1 << 29);
+#if CONFIG_MAX_PHYSICAL_CPUS==1
+	// IRT 80us RVO = 50mV PLL_LOCK_TIME 2us, MVS 25mv, VST 100us
+	control = (3 << 30) | (2 << 28) | (2 << 20) | (0 << 18) | (5 << 11);
+#else
+	// MP-systems should default to RVO=0mV (no ramp voltage)
+	// IRT 80us RVO = 0mV PLL_LOCK_TIME 2us, MVS 25mv, VST 100us
+	control = (3 << 30) | (0 << 28) | (2 << 20) | (0 << 18) | (5 << 11);
+#endif
+	// RVO (Ramp Voltage Offset)
+	//   00   0mV (default for MP-systems)
+	//   01  25mV
+	//   10  50mV (default)
+	//   11  75mV
+	// IRT (Isochronous Release Time)
+	//   00  10uS
+	//   01  20uS
+	//   10  40uS
+	//   11  80uS (default)
+	// MVS (Maximum Voltage Step)
+	//   00  25mV (default)
+	//   01  50mV (reserved)
+	//   10 100mV (reserved)
+	//   11 200mV (reserved)
+	// VST (Voltage Stabilization Time)
+	//   time = value*20uS  (default value: 5 => 100uS)
+	// PLL_LOCK_TIME
+	//   time is value*1uS (often seen value: 2uS)
+	//
+
 	len = 0;
-	Pstate_num = 0;
 
-	Pstate_fid[Pstate_num] = Max_fid;
-	Pstate_feq[Pstate_num] = fid_to_freq(Max_fid);
-	Pstate_vid[Pstate_num] = Max_vid;
-	Pstate_power[Pstate_num] = data->pwr * 100;
-	Pstate_num++;
+	Pstate_fid[0] = Max_fid;
+	Pstate_feq[0] = fid_to_freq(Max_fid);
+	Pstate_vid[0] = Max_vid;
+	Pstate_power[0] = data->pwr * 100;
 
-	do {
+	for(Pstate_num = 1;
+	    (Pstate_num <= MAXP) && (data->pstates[Pstate_num - 1].freqMhz != 0);
+	    Pstate_num++) {
 		Pstate_fid[Pstate_num] = freq_to_fid(data->pstates[Pstate_num - 1].freqMhz) & 0x3f;
 		Pstate_feq[Pstate_num] = data->pstates[Pstate_num - 1].freqMhz;
 		Pstate_vid[Pstate_num] = vid_to_reg(data->pstates[Pstate_num - 1].voltage);
 		Pstate_power[Pstate_num] = data->pstates[Pstate_num - 1].tdp * 100;
-		Pstate_num++;
-	} while ((Pstate_num < MAXP) && (data->pstates[Pstate_num - 1].freqMhz != 0));
+	}
 
 	for (i=0;i<Pstate_num;i++)
 		printk(BIOS_DEBUG, "P#%d freq %d [MHz] voltage %d [mV] TDP %d [mW]\n", i,
@@ -645,11 +682,18 @@ static int pstates_algorithm(u32 pcontrol_blk, u8 plen, u8 onlyBSP)
 		       vid_from_reg(Pstate_vid[i]),
 		       Pstate_power[i]);
 
-	for (index = 0; index < (cmp_cap + 1); index++) {
-		len += write_pstates_for_core(Pstate_num, Pstate_feq, Pstate_vid,
-				Pstate_fid, Pstate_power, index,
-				pcontrol_blk, plen, onlyBSP, control);
+	for (dev = 0x18; dev < 0x1c; dev++) {
+		if(dev_find_slot(0, PCI_DEVFN(dev, 0))==NULL)
+			continue;
+
+		for (i = 0; i < (cmp_cap + 1); i++) {
+			len += write_pstates_for_core(Pstate_num, Pstate_feq, Pstate_vid,
+					Pstate_fid, Pstate_power, index+i,
+					pcontrol_blk, plen, onlyBSP, control);
+		}
+		index += i;
 	}
+	printk(BIOS_DEBUG,"%d Processor objects emitted to SSDT\n",index);
 
 	return len;
 }




More information about the coreboot mailing list