Commit 92b51eda authored by Dave Jones's avatar Dave Jones

Merge delerium.codemonkey.org.uk:/mnt/nfs/sepia/bar/src/kernel/2.6/trees/bk-linus

into delerium.codemonkey.org.uk:/mnt/nfs/sepia/bar/src/kernel/2.6/trees/cpufreq
parents 4d72de23 7b349554
......@@ -85,6 +85,14 @@ static unsigned int fsb;
static unsigned int latency;
static char have_a0;
static int check_fsb(unsigned int fsbspeed)
{
int delta;
unsigned int f = fsb / 1000;
delta = (fsbspeed > f) ? fsbspeed - f : f - fsbspeed;
return (delta < 5);
}
static int check_powernow(void)
{
......@@ -140,7 +148,8 @@ static int check_powernow(void)
static int get_ranges (unsigned char *pst)
{
unsigned int j, speed;
unsigned int j;
unsigned int speed;
u8 fid, vid;
powernow_table = kmalloc((sizeof(struct cpufreq_frequency_table) * (number_scales + 1)), GFP_KERNEL);
......@@ -151,12 +160,12 @@ static int get_ranges (unsigned char *pst)
for (j=0 ; j < number_scales; j++) {
fid = *pst++;
powernow_table[j].frequency = fsb * fid_codes[fid] * 100;
powernow_table[j].frequency = (fsb * fid_codes[fid]) / 10;
powernow_table[j].index = fid; /* lower 8 bits */
speed = fsb * (fid_codes[fid]/10);
speed = powernow_table[j].frequency;
if ((fid_codes[fid] % 10)==5) {
speed += fsb/2;
#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
if (have_a0 == 1)
powernow_table[j].frequency = CPUFREQ_ENTRY_INVALID;
......@@ -164,7 +173,7 @@ static int get_ranges (unsigned char *pst)
}
dprintk (KERN_INFO PFX " FID: 0x%x (%d.%dx [%dMHz])\t", fid,
fid_codes[fid] / 10, fid_codes[fid] % 10, speed);
fid_codes[fid] / 10, fid_codes[fid] % 10, speed/1000);
if (speed < minimum_speed)
minimum_speed = speed;
......@@ -234,7 +243,8 @@ static void change_speed (unsigned int index)
rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);
cfid = fidvidstatus.bits.CFID;
freqs.old = fsb * fid_codes[cfid] * 100;
freqs.old = fsb * fid_codes[cfid] / 10;
freqs.new = powernow_table[index].frequency;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
......@@ -266,15 +276,12 @@ static int powernow_decode_bios (int maxfid, int startvid)
{
struct psb_s *psb;
struct pst_s *pst;
struct cpuinfo_x86 *c = cpu_data;
unsigned int i, j;
unsigned char *p;
unsigned int etuple;
unsigned int ret;
etuple = cpuid_eax(0x80000001);
etuple &= 0xf00;
etuple |= (c->x86_model<<4)|(c->x86_mask);
for (i=0xC0000; i < 0xffff0 ; i+=16) {
......@@ -305,7 +312,6 @@ static int powernow_decode_bios (int maxfid, int startvid)
}
dprintk (KERN_INFO PFX "Settling Time: %d microseconds.\n", psb->settlingtime);
dprintk (KERN_INFO PFX "Has %d PST tables. (Only dumping ones relevant to this CPU).\n", psb->numpst);
latency *= 100; /* SGTC needs to be in units of 10ns */
p += sizeof (struct psb_s);
......@@ -315,7 +321,8 @@ static int powernow_decode_bios (int maxfid, int startvid)
pst = (struct pst_s *) p;
number_scales = pst->numpstates;
if ((etuple == pst->cpuid) && (maxfid==pst->maxfid) && (startvid==pst->startvid))
if ((etuple == pst->cpuid) && check_fsb(pst->fsbspeed) &&
(maxfid==pst->maxfid) && (startvid==pst->startvid))
{
dprintk (KERN_INFO PFX "PST:%d (@%p)\n", i, pst);
dprintk (KERN_INFO PFX " cpuid: 0x%x\t", pst->cpuid);
......@@ -323,7 +330,6 @@ static int powernow_decode_bios (int maxfid, int startvid)
dprintk ("maxFID: 0x%x\t", pst->maxfid);
dprintk ("startvid: 0x%x\n", pst->startvid);
fsb = pst->fsbspeed;
ret = get_ranges ((char *) pst + sizeof (struct pst_s));
return ret;
......@@ -365,6 +371,33 @@ static int powernow_verify (struct cpufreq_policy *policy)
return cpufreq_frequency_table_verify(policy, powernow_table);
}
/*
* We use the fact that the bus frequency is somehow
* a multiple of 100000/3 khz, then we compute sgtc according
* to this multiple.
* That way, we match more how AMD thinks all of that work.
* We will then get the same kind of behaviour already tested under
* the "well-known" other OS.
*/
static int __init fixup_sgtc(void)
{
unsigned int sgtc;
unsigned int m;
m = fsb / 3333;
if ((m % 10) >= 5)
m += 5;
m /= 10;
sgtc = 100 * m * latency;
sgtc = sgtc / 3;
if (sgtc > 0xfffff) {
printk(KERN_WARNING PFX "SGTC too large %d\n", sgtc);
sgtc = 0xfffff;
}
return sgtc;
}
static int __init powernow_cpu_init (struct cpufreq_policy *policy)
{
......@@ -376,18 +409,28 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy)
rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);
/* A K7 with powernow technology is set to max frequency by BIOS */
fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.MFID];
if (!fsb) {
printk(KERN_WARNING PFX "can not determine bus frequency\n");
return -EINVAL;
}
dprintk(KERN_INFO PFX "FSB: %3d.%03d MHz\n", fsb/1000, fsb%1000);
result = powernow_decode_bios(fidvidstatus.bits.MFID, fidvidstatus.bits.SVID);
if (result)
return result;
printk (KERN_INFO PFX "Minimum speed %d MHz. Maximum speed %d MHz.\n",
minimum_speed, maximum_speed);
minimum_speed/1000, maximum_speed/1000);
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
/* latency is in 10 ns (look for SGTC above) for each VID
* and FID transition, so multiply that value with 20 */
policy->cpuinfo.transition_latency = latency * 20;
policy->cpuinfo.transition_latency = latency * 2;
/* SGTC use the bus clock as timer */
latency = fixup_sgtc();
printk(KERN_INFO PFX "SGTC: %d\n", latency);
policy->cur = maximum_speed;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment