It adds support for automatic PSS object generation for AMD pre fam Fh CPU. Those...
authorRudolf Marek <r.marek@asssembler.cz>
Sat, 26 Feb 2011 13:34:01 +0000 (13:34 +0000)
committerRudolf Marek <r.marek@assembler.cz>
Sat, 26 Feb 2011 13:34:01 +0000 (13:34 +0000)
Also it enables the FID/VID changes in SB. Jakllsch had some troubles with that too but on am2 CPU. Those bits are only documented in SB600. They arent in RRG RPR and BDG.

Signed-off-by: Rudolf Marek <r.marek@asssembler.cz>
Acked-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@6381 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1

src/cpu/amd/model_fxx/powernow_acpi.c
src/southbridge/amd/sb700/early_setup.c

index b07dcb1a96fb0a9db50205385fe6884785f3da31..09f6ae56d71fed9157edde35a7eb1b541492a7be 100644 (file)
 #include <cpu/amd/amdk8_sysconf.h>
 #include <arch/cpu.h>
 
-#if CONFIG_K8_REV_F_SUPPORT
 static int write_pstates_for_core(u8 pstate_num, u16 *pstate_feq, u8 *pstate_vid,
                                u8 *pstate_fid, u32 *pstate_power, int coreID,
-                               u32 pcontrol_blk, u8 plen, u8 onlyBSP)
+                               u32 pcontrol_blk, u8 plen, u8 onlyBSP, u32 control)
 {
        int lenp, lenpr, i;
 
@@ -50,16 +49,8 @@ static int write_pstates_for_core(u8 pstate_num, u16 *pstate_feq, u8 *pstate_vid
        lenp = acpigen_write_package(pstate_num);
 
        for (i = 0;i < pstate_num;i++) {
-               u32 control, status;
-
-               control =
-                           (0x3 << 30) | /* IRT */
-                           (0x2 << 28) | /* RVO */
-                           (0x1 << 27) | /* ExtType */
-                           (0x2 << 20) | /* PLL_LOCK_TIME */
-                           (0x0 << 18) | /* MVS */
-                           (0x5 << 11) | /* VST */
-                           (pstate_vid[i] << 6) |
+               u32 status, c2;
+               c2 = control | (pstate_vid[i] << 6) |
                            pstate_fid[i];
                status =
                            (pstate_vid[i] << 6) |
@@ -69,7 +60,7 @@ static int write_pstates_for_core(u8 pstate_num, u16 *pstate_feq, u8 *pstate_vid
                                                pstate_power[i],
                                                0x64,
                                                0x7,
-                                               control,
+                                               c2,
                                                status);
        }
        /* update the package  size */
@@ -81,6 +72,8 @@ static int write_pstates_for_core(u8 pstate_num, u16 *pstate_feq, u8 *pstate_vid
        acpigen_patch_len(lenpr - 2);
        return lenpr;
 }
+
+#if CONFIG_K8_REV_F_SUPPORT
 /*
 * Details about this algorithm , refert to BDKG 10.5.1
 * Two parts are included, the another is the DSDT reconstruction process
@@ -90,7 +83,7 @@ static int pstates_algorithm(u32 pcontrol_blk, u8 plen, u8 onlyBSP)
 {
        int len;
        u8 processor_brand[49];
-       u32 *v;
+       u32 *v, control;
        struct cpuid_result cpuid1;
 
        struct power_limit_encoding {
@@ -367,15 +360,288 @@ write_pstates:
 
        len = 0;
 
+       control = (0x3 << 30) | /* IRT */
+                 (0x2 << 28) | /* RVO */
+                 (0x1 << 27) | /* ExtType */
+                 (0x2 << 20) | /* PLL_LOCK_TIME */
+                 (0x0 << 18) | /* MVS */
+                 (0x5 << 11); /* VST */
+
+       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);
+       }
+
+       return len;
+}
+
+#else
+
+
+static uint8_t vid_to_reg(uint32_t vid)
+{
+       return (1550 - vid) / 25;
+}
+
+static uint32_t vid_from_reg(uint8_t val)
+{
+       return (val == 0x1f ? 0 : 1550 - val * 25);
+}
+
+static uint8_t freq_to_fid(uint32_t freq)
+{
+       return (freq - 800) / 100;
+}
+/* Return a frequency in MHz, given an input fid */
+static uint32_t fid_to_freq(uint32_t fid)
+{
+       return 800 + (fid * 100);
+}
+
+#define MAXP 7
+
+struct pstate {
+       uint16_t freqMhz; /* in MHz */
+       uint16_t voltage; /* in mV */
+       uint16_t tdp; /* in W * 10 */
+};
+
+struct cpuentry {
+       uint16_t modelnr; /* numeric model value, unused in code */
+       uint8_t brandID; /* CPUID 8000_0001h EBX [11:6] (BrandID) */
+       uint32_t cpuid; /* CPUID 8000_0001h EAX [31:0] (CPUID) */
+       uint8_t maxFID; /* FID/VID Status MaxFID Field */
+       uint8_t startFID; /* FID/VID Status StartFID Field */
+       uint16_t pwr:12; /* Thermal Design Power of Max P-State  *10 (fixed point) */
+       /* Other MAX P state are read from CPU, other P states in following table */
+       struct pstate pstates[MAXP];
+};
+
+struct cpuentry entr[] = {
+       /* rev E single core, check OSA152FAA5BK */
+       {152, 0xc, 0x20f51, 0x12, 0x12, 926,
+        {{2400, 1350, 900}, {2200, 1300, 766},
+         {2000, 1250, 651}, {1800, 1200, 522},
+         {1000, 1100, 320}}},
+       {252, 0x10, 0x20f51, 0x12, 0x12, 926,
+        {{2400, 1350, 900}, {2200, 1300, 766},
+         {2000, 1250, 651}, {1800, 1200, 522},
+         {1000, 1100, 320}}},
+       {852, 0x14, 0x20f51, 0x12, 0x12, 926,
+        {{2400, 1350, 900}, {2200, 1300, 766},
+         {2000, 1250, 651}, {1800, 1200, 522},
+         {1000, 1100, 320}}},
+       {254, 0x10, 0x20f51, 0x14, 0x14, 926,
+        {{2600, 1350, 902}, {2400, 1300, 770},
+         {2200, 1250, 657}, {2000, 1200, 559},
+         {1800, 1150, 476}, {1000, 1100, 361}}},
+       {854, 0x14, 0x20f51, 0x14, 0x14, 926,
+        {{2600, 1350, 902}, {2400, 1300, 770},
+         {2200, 1250, 657}, {2000, 1200, 559},
+         {1800, 1150, 476}, {1000, 1100, 361}}},
+       {242, 0x10, 0x20f51, 0x8, 0x8, 853,
+        {}},
+       {842, 0x10, 0x20f51, 0x8, 0x8, 853,
+        {}},
+       {244, 0x10, 0x20f51, 0xa, 0xa, 853,
+        {{1000, 1100, 378}}},
+       {844, 0x14, 0x20f51, 0xa, 0xa, 853,
+        {{1000, 1100, 378}}},
+       {246, 0x10, 0x20f51, 0xc, 0xc, 853,
+        {{1800, 1350, 853},
+        {1000, 1100, 378}}},
+       {846, 0x14, 0x20f51, 0xc, 0xc, 853,
+        {{1800, 1350, 853},
+        {1000, 1100, 378}}},
+       {242, 0x10, 0x20f51, 0x8, 0x8, 853,
+        {}},
+       {842, 0x14, 0x20f51, 0x8, 0x8, 853,
+        {}},
+       {244, 0x10, 0x20f51, 0xa, 0xa, 853,
+        {{1000, 1100, 378}}},
+       {844, 0x14, 0x20f51, 0xa, 0xa, 853,
+        {{1000, 1100, 378}}},
+       {246, 0x10, 0x20f51, 0xc, 0xc, 853,
+        {{1800, 1350, 827}, {1000, 1100, 366}}},
+       {846, 0x14, 0x20f51, 0xc, 0xc, 853,
+        {{1800, 1350, 827}, {1000, 1100, 366}}},
+       {248, 0x10, 0x20f51, 0xe, 0xe, 853,
+        {{2000, 1350, 827}, {1800, 1300, 700},
+         {1000, 1100, 366}}},
+       {848, 0x14, 0x20f51, 0xe, 0xe, 853,
+        {{2000, 1350, 827}, {1800, 1300, 700},
+         {1000, 1100, 366}}},
+       {250, 0x10, 0x20f51, 0x10, 0x10, 853,
+        {{2200, 1350, 853}, {2000, 1300, 827},
+         {1800, 1250, 702}, {1000, 1100, 301}}},
+       {850, 0x14, 0x20f51, 0x10, 0x10, 853,
+        {{2200, 1350, 853}, {2000, 1300, 827},
+         {1800, 1250, 702}, {1000, 1100, 301}}},
+/* begin OSK246FAA5BL */
+       {246, 0x12, 0x20f51, 0xc, 0xc, 547,
+        {{1800, 1350, 461}, {1000, 1100, 223}}},
+       {846, 0x16, 0x20f51, 0xc, 0xc, 547,
+        {{1800, 1350, 461}, {1000, 1100, 223}}},
+       {148, 0xe, 0x20f51, 0xe, 0xe, 547,
+        {{2000, 1350, 521}, {1800, 1300, 459},
+         {1000, 1100, 211}}},
+       {248, 0x12, 0x20f51, 0xe, 0xe, 547,
+        {{2000, 1350, 521}, {1800, 1300, 459},
+         {1000, 1100, 211}}},
+       {848, 0x16, 0x20f51, 0xe, 0xe, 547,
+        {{2000, 1350, 521}, {1800, 1300, 459},
+         {1000, 1100, 211}}},
+       {250, 0x12, 0x20f51, 0x10, 0x10, 547,
+        {{2200, 1350, 521}, {2000, 1300, 440},
+         {1800, 1250, 379}, {1000, 1100, 199}}},
+       {850, 0x16, 0x20f51, 0x10, 0x10, 547,
+        {{2200, 1350, 521}, {2000, 1300, 440},
+         {1800, 1250, 379}, {1000, 1100, 199}}},
+       {144, 0xc, 0x20f71, 0xa, 0xa, 670,
+        {{1000, 1100, 296}}},
+       {148, 0xc, 0x20f71, 0xe, 0xe, 853,
+        {{2000, 1350, 830}, {1800, 1300, 704},
+        {1000, 1100, 296}}},
+       {152, 0xc, 0x20f71, 0x12, 0x12, 104,
+        {{2400, 1350, 1016}, {2200, 1300, 863},
+        {2000, 1250, 732}, {1800, 1200, 621},
+         {1000, 1100, 419}}},
+       {146, 0xc, 0x20f71, 0xc, 0xc, 670,
+        {{1800, 1350, 647}, {1000, 1100, 286}}},
+       {150, 0xc, 0x20f71, 0x10, 0x10, 853,
+       {{2200, 1350, 830}, {2000, 1300, 706},
+       {1800, 1250, 596}, {1000, 1100, 350}}},
+       {154, 0xc, 0x20f71, 0x14, 0x14, 1040,
+       {{2600, 1350, 1017}, {2400, 1300, 868},
+       {2200, 1250, 740}, {2000, 1200, 630},
+       {1800, 1150, 537}, {1000, 1100, 416}}},
+       /* rev E dualcore */
+       {165, 0x2c, 0x20f12, 0xa, 0xa, 950,
+        {{1000, 1100, 406}}},
+       {265, 0x30, 0x20f12, 0xa, 0xa, 950,
+        {{1000, 1100, 406}}},
+       {865, 0x34, 0x20f12, 0xa, 0xa, 950,
+        {{1000, 1100, 406}}},
+       {270, 0x30, 0x20f12, 0xc, 0xc, 950,
+        {{1800, 1300, 903}, {1000, 1100, 383}}},
+       {870, 0x34, 0x20f12, 0xc, 0xc, 950,
+        {{1800, 1300, 903}, {1000, 1100, 383}}},
+       {275, 0x30, 0x20f12, 0xe, 0xe, 950,
+        {{2000, 1300, 903}, {1800, 1250, 759},
+        {1000, 1100, 361}}},
+       {875, 0x34, 0x20f12, 0xe, 0xe, 950,
+        {{2000, 1300, 903}, {1800, 1250, 759},
+        {1000, 1100, 361}}},
+       {280, 0x30, 0x20f12, 0x10, 0x10, 926,
+        {{2400, 1350, 900}, {2200, 1300, 766},
+        {1800, 1200, 552}, {1000, 1100, 320}}},
+       {880, 0x34, 0x20f12, 0x10, 0x10, 926,
+        {{2400, 1350, 900}, {2200, 1300, 766},
+        {1800, 1200, 552}, {1000, 1100, 320}}},
+       {170, 0x2c, 0x20f32, 0xc, 0xc, 1100,
+        {{1800, 1300, 1056}, {1000, 1100, 514}}},
+       {175, 0x2c, 0x20f32, 0xe, 0xe, 1100,
+        {{2000, 1300, 1056}, {1800, 1250, 891},
+         {1000, 1100, 490}}},
+       {260, 0x32, 0x20f32, 0x8, 0x8, 550,
+        {}},
+       {860, 0x36, 0x20f32, 0x8, 0x8, 550,
+        {}},
+       {165, 0x2e, 0x20f32, 0xa, 0xa, 550,
+        {{1000, 1100, 365}}},
+       {265, 0x32, 0x20f32, 0xa, 0xa, 550,
+        {{1000, 1100, 365}}},
+       {865, 0x36, 0x20f32, 0xa, 0xa, 550,
+        {{1000, 1100, 365}}},
+       {270, 0x32, 0x20f12, 0xc, 0xc, 550,
+        {{1800, 1150, 520}, {1000, 1100, 335}}},
+       {870, 0x36, 0x20f12, 0xc, 0xc, 550,
+        {{1800, 1150, 520}, {1000, 1100, 335}}},
+       {180, 0x2c, 0x20f32, 0x10, 0x10, 1100,
+        {{2200, 1300, 1056}, {2000, 1250, 891},
+         {1800, 1200, 748}, {1000, 1100, 466}}},
+       {3000, 0x4, 0x10ff0, 0xa, 0xa, 670,
+        {{1000, 1100, 210}}},
+};
+
+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;
+       msr_t msr;
+       u8 Pstate_fid[10];
+       u16 Pstate_feq[10];
+       u8 Pstate_vid[10];
+       u32 Pstate_power[10];
+       u8 Max_fid, Start_fid, Start_vid, Max_vid;
+       struct cpuid_result cpuid1 = cpuid(0x80000001);
+
+       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;
+
+       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;
+               }
+       }
+
+       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;
+               Pstate_num++;
+       } while ((Pstate_num < MAXP) && (data->pstates[Pstate_num].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]);
+
        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);
+                               pcontrol_blk, plen, onlyBSP, control);
        }
 
        return len;
 }
 
+#endif
+
+
 int amd_model_fxx_generate_powernow(u32 pcontrol_blk, u8 plen, u8 onlyBSP)
 {
        int lens;
@@ -388,11 +654,3 @@ int amd_model_fxx_generate_powernow(u32 pcontrol_blk, u8 plen, u8 onlyBSP)
        return lens;
 }
 
-#else
-
-int amd_model_fxx_generate_powernow(u32 pcontrol_blk, u8 plen, u8 onlyBSP)
-{
-       return 0;
-}
-
-#endif
index 552086a7ebc190e5b78ada7083c33f257e5a97ba..383b24f577510cd7187e0b303ddaa3259ecf9305 100644 (file)
@@ -232,6 +232,12 @@ static void enable_fid_change_on_sb(u32 sbbusn, u32 sbdn)
        pmio_write(0x42, byte);
 
        pmio_write(0x89, 0x10);
+
+       /* Toggle the LDT_STOP# during FID/VID Change, this bit is documented
+          only in SB600!
+          While here, enable C states too
+       */
+       pmio_write(0x67, 0x6);
 }
 
 void hard_reset(void)