Oskar Enoksson ([email protected]) just uploaded a new patch set to gerrit, 
which you can find at http://review.coreboot.org/239

-gerrit

commit af6f38bbfbf7702a5c432a6275e58dd13ce318bd
Author: Oskar Enoksson <[email protected]>
Date:   Thu Oct 6 18:43:43 2011 +0200

    Fixes several issues with amd k8 SSDT P-state generation
    
    For multi-socket CPU the current implementation emitted
    Processor objects for cores in the first CPU only. This
    commit fixes the bug. One caveat though: the unlikely case
    of CPU's with different FID/VID capabilities mixed in the
    same system is not handled correctly.
    
    Second issue fixed: processors not supporting P-state
    transitions got no Processor objects at all. It's probably
    better to give them a Processor object with one single P-state.
    The old loop also looked wrong in case a processor
    in the table doesn't have any declared 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 if the
    number of populated CPU sockets is >1 or not.
    
    Signed-off-by: Oskar Enoksson <[email protected]>
    Change-Id: I61f6e2210b84ccba33a36c5efc866447b7134417
---
 src/cpu/amd/model_fxx/powernow_acpi.c |  155 ++++++++++++++++++++++-----------
 1 files changed, 103 insertions(+), 52 deletions(-)

diff --git a/src/cpu/amd/model_fxx/powernow_acpi.c 
b/src/cpu/amd/model_fxx/powernow_acpi.c
index bbcf013..65bbd90 100644
--- a/src/cpu/amd/model_fxx/powernow_acpi.c
+++ b/src/cpu/amd/model_fxx/powernow_acpi.c
@@ -586,70 +586,121 @@ 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, isock = 0, nsock = 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);
+       unsigned sockets[] = { 0x18, 0x19, 0x1a, 0x1b };
+       struct cpuentry entr_dummy = {.pstates[0].freqMhz = 0 };
 
-       msr = rdmsr(0xc0010042);
-       Max_fid = (msr.lo & 0x3F0000) >> 16;
-       Max_vid = (msr.hi & 0x3F0000) >> 16;
-       Start_fid = (msr.lo & 0x3F00) >> 8;
-       Start_vid = (msr.hi & 0x3F00) >> 8;
-
-       cmp_cap =
-           (pci_read_config16(dev_find_slot(0, PCI_DEVFN(0x18, 3)), 0xE8) &
-            0x3000) >> 12;
+       // Count number of populated sockets
+       for (isock = 0,nsock = 0; isock < ARRAY_SIZE(sockets); isock++) {
+               if(dev_find_slot(0, PCI_DEVFN(sockets[isock], 0))!=NULL)
+                       nsock++;
+       }
+               
+       for (isock = 0; isock < ARRAY_SIZE(sockets); isock++) {
+               if(dev_find_slot(0, PCI_DEVFN(sockets[isock], 0))==NULL)
+                       continue;
+               // TODO: We should read msr from the right CPU here
+               // The following only works if fid/vid values are identical on
+               // all CPU's
+               msr = rdmsr(0xc0010042);
+               Max_fid = (msr.lo & 0x3F0000) >> 16;
+               Max_vid = (msr.hi & 0x3F0000) >> 16;
+               Start_fid = (msr.lo & 0x3F00) >> 8;
+               Start_vid = (msr.hi & 0x3F00) >> 8;
+
+               cmp_cap =
+                   (pci_read_config16(dev_find_slot(0, 
PCI_DEVFN(sockets[isock], 3)), 0xE8) &
+                    0x3000) >> 12;
+
+               for (i = 0; i < ARRAY_SIZE(entr); i++) {
+                       if ((entr[i].cpuid == cpuid1.eax)
+                           && (entr[i].startFID == Start_fid)
+                           && (entr[i].maxFID == Max_fid)
+                           && (entr[i].brandID == ((u8 )((cpuid1.ebx >> 6) & 
0xff)))) {
+                               data = &entr[i];
+                               break;
+                       }
+               }
 
-       for (i = 0; i < ARRAY_SIZE(entr); i++) {
-               if ((entr[i].cpuid == cpuid1.eax)
-                   && (entr[i].startFID == Start_fid)
-                   && (entr[i].maxFID == Max_fid)
-                   && (entr[i].brandID == ((u8 )((cpuid1.ebx >> 6) & 0xff)))) {
-                       data = &entr[i];
+               if (data == NULL) {
+                       printk(BIOS_WARNING, "Unknown CPU in socket %d, please 
update powernow_acpi.c\n",isock);
+                       data = &entr_dummy;
+               }
+               /* See if the CPUID(0x80000007) returned EDX[2:1]==11b */
+               cpuid1 = cpuid(0x80000007);
+               switch ((cpuid1.edx & 0x6)) {
+               case 0x6:
+                       break;
+               case 0x0:
+                       printk(BIOS_INFO, "Processor not capable of performing 
P-state transitions\n");
+                       data = &entr_dummy;
+                       break;
+               default:
+                       printk(BIOS_WARNING, "Capability of performing P-state 
transitions unknown\n");
                        break;
                }
-       }
-
-       if (data == NULL) {
-               printk(BIOS_WARNING, "Unknown CPU, please update the 
powernow_acpi.c\n");
-               return 0;
-       }
-
-       /* IRT 80us, PLL_LOCK_TIME 2us, MVS 25mv, VST 100us */
-       control = (3 << 30) | (2 << 20) | (0 << 18) | (5 << 11) | (1 << 29);
-       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++;
-
-       do {
-               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;
+               if(nsock==1)
+                       // IRT 80us, PLL_LOCK_TIME 2us, MVS 25mv, VST 100us RVO 
= 50mV
+                       control = (3 << 30) | (2 << 20) | (0 << 18) | (5 << 11) 
| (1 << 29);
+               else
+                       // MP-systems should default to RVO=0mV (no ramp 
voltage)
+                       // IRT 80us, PLL_LOCK_TIME 2us, MVS 25mv, VST 100us RVO 
= 0mV
+                       control = (3 << 30) | (2 << 20) | (0 << 18) | (5 << 11) 
| (0 << 29);
+               // RVO:  00   0mV (default for MP-systems)
+               //       01  25mV
+               //       10  50mV (default)
+               //       11  75mV
+               // IRT:  00  10uS
+               //       01  20uS
+               //       10  40uS
+               //       11  80uS (default)
+               // MVS:  00  25mV (default)
+               //       01  50mV (reserved)
+               //       10 100mV (reserved)
+               //       11 200mV (reserved)
+               // VST:  time is 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++;
-       } 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,
-                      Pstate_feq[i],
-                      vid_from_reg(Pstate_vid[i]),
-                      Pstate_power[i]);
+               while ((Pstate_num <= MAXP) && (data->pstates[Pstate_num - 
1].freqMhz != 0)) {
+                       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++;
+               }
 
-       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 (i=0;i<Pstate_num;i++)
+                       printk(BIOS_DEBUG, "P#%d freq %d [MHz] voltage %d [mV] 
TDP %d [mW]\n", i,
+                              Pstate_feq[i],
+                              vid_from_reg(Pstate_vid[i]),
+                              Pstate_power[i]);
+
+               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 will be emitted to 
SSDT\n",index);
 
        return len;
 }

-- 
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to