Hi all,
This is RFC patch. It adds support for automatic PSS object generation for AMD
pre fam Fh CPU. Those CPUs require a hardcoded table, which I managed to rewrite
during one particularly boring flight. Too pity it is only for Opteron CPUs.
Someone needs to finish the second PDF for All others Athlons and Semprons.
It just adds the table to same place where is the fam0fh generator. To make the
powernow work on my Asrock 939 board I had to enable undocumented bit1 in
PM_Misc 67h of SB710. It looks like this bit is documented in SB600 and it is
doing LDT_STOP toggle for C states (and for FID/VID). I remember I had to fix
this toggle for VIA chipset too. It took me some time to figure it out. It
helped that it started to work if the orig bios was booted and halted to S5.
All search was to find out what register was not updated by coreboot).
Whom to ask to fix the AMD documentation?
It is unknown if the bit is necessary for fam 0fh or fam10h, question is if the
second bit CC_en which says: "C State enable. This bit must be set in order to
exercise the C state" should be enabled (it is for me with orig BIOS).
Thanks,
Rudolf
Index: src/cpu/amd/model_fxx/powernow_acpi.c
===================================================================
--- src/cpu/amd/model_fxx/powernow_acpi.c.orig 2010-10-16 09:09:24.000000000 +0200
+++ src/cpu/amd/model_fxx/powernow_acpi.c 2010-12-25 18:13:19.000000000 +0100
@@ -30,10 +30,9 @@
#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 @@
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 @@
pstate_power[i],
0x64,
0x7,
- control,
+ c2,
status);
}
/* update the package size */
@@ -81,6 +72,8 @@
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 @@
{
int len;
u8 processor_brand[49];
- u32 *v;
+ u32 *v, control;
struct cpuid_result cpuid1;
struct power_limit_encoding {
@@ -367,15 +360,289 @@
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);
+ 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;
+}
+//from kernel
+/* 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;
+ uint16_t voltage;
+ uint16_t tdp;
+};
+
+struct cpuentry {
+ uint16_t modelnr;
+ uint8_t brandID;
+ uint32_t cpuid;
+ uint8_t maxFID;
+ uint8_t startFID;
+ uint16_t pwr:12;
+ struct pstate pstates[MAXP];
+};
+
+struct cpuentry entr[] = {
+ /*rev E single core */
+ {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, control);
+ }
+
+ return len;
+}
+
+#endif
+
+
int amd_model_fxx_generate_powernow(u32 pcontrol_blk, u8 plen, u8 onlyBSP)
{
int lens;
@@ -388,11 +655,3 @@
return lens;
}
-#else
-
-int amd_model_fxx_generate_powernow(u32 pcontrol_blk, u8 plen, u8 onlyBSP)
-{
- return 0;
-}
-
-#endif
Index: src/southbridge/amd/sb700/early_setup.c
===================================================================
--- src/southbridge/amd/sb700/early_setup.c.orig 2010-12-25 17:10:23.000000000 +0100
+++ src/southbridge/amd/sb700/early_setup.c 2010-12-25 17:12:23.000000000 +0100
@@ -231,6 +231,11 @@
pmio_write(0x42, byte);
pmio_write(0x89, 0x10);
+
+ /* Toggle the LDT_STOP# during FID/VID Change, this bit is documented
+ only in SB600!
+ */
+ pmio_write(0x67, 0x2);
}
void hard_reset(void)
--
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot