From 199c694f49e2ecbc3bd2cc6c5e7d7570a4c3cf62 Mon Sep 17 00:00:00 2001 From: Rudolf Marek Date: Sat, 26 Feb 2011 13:34:01 +0000 Subject: 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. 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 Acked-by: Stefan Reinauer git-svn-id: svn://svn.coreboot.org/coreboot/trunk@6381 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- src/cpu/amd/model_fxx/powernow_acpi.c | 304 +++++++++++++++++++++++++++++++--- 1 file changed, 281 insertions(+), 23 deletions(-) (limited to 'src/cpu/amd') diff --git a/src/cpu/amd/model_fxx/powernow_acpi.c b/src/cpu/amd/model_fxx/powernow_acpi.c index b07dcb1a96..09f6ae56d7 100644 --- a/src/cpu/amd/model_fxx/powernow_acpi.c +++ b/src/cpu/amd/model_fxx/powernow_acpi.c @@ -30,10 +30,9 @@ #include #include -#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