Skip to content

Commit

Permalink
[CPUFREQ] powernow-k8: determine exact CPU frequency for HW Pstates
Browse files Browse the repository at this point in the history
Slightly modified by trenn@suse.de -> only do this on fam 10h and fam 11h.

Currently powernow-k8 determines CPU frequency from ACPI PSS objects, but
according to AMD family 11h BKDG this frequency is just a rounded value:

  "CoreFreq (MHz) = The CPU COF specified by MSRC001_00[6B:64][CpuFid]
  rounded to the nearest 100 Mhz."

As a consequnce powernow-k8 reports wrong CPU frequency on some systems,
e.g. on Turion X2 Ultra:

  powernow-k8: Found 1 AMD Turion(tm)X2 Ultra DualCore Mobile ZM-82
               processors (2 cpu cores) (version 2.20.00)
  powernow-k8:    0 : pstate 0 (2200 MHz)
  powernow-k8:    1 : pstate 1 (1100 MHz)
  powernow-k8:    2 : pstate 2 (600 MHz)

But this is wrong as frequency for Pstate2 is 550 MHz. x86info reports it
correctly:

  #x86info -a |grep Pstate
  ...
  Pstate-0: fid=e, did=0, vid=24 (2200MHz)
  Pstate-1: fid=e, did=1, vid=30 (1100MHz)
  Pstate-2: fid=e, did=2, vid=3c (550MHz) (current)

Solution is to determine the frequency directly from Pstate MSRs instead
of using rounded values from ACPI table.

Signed-off-by: Andreas Herrmann <andreas.herrmann3@amd.com>
Signed-off-by: Thomas Renninger <trenn@suse.de>
Signed-off-by: Dave Jones <davej@redhat.com>
  • Loading branch information
Andreas Herrmann authored and Dave Jones committed May 26, 2009
1 parent df18297 commit ca446d0
Showing 1 changed file with 21 additions and 2 deletions.
23 changes: 21 additions & 2 deletions arch/x86/kernel/cpu/cpufreq/powernow-k8.c
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,20 @@ static void print_basics(struct powernow_k8_data *data)
data->batps);
}

static u32 freq_from_fid_did(u32 fid, u32 did)
{
u32 mhz = 0;

if (boot_cpu_data.x86 == 0x10)
mhz = (100 * (fid + 0x10)) >> did;
else if (boot_cpu_data.x86 == 0x11)
mhz = (100 * (fid + 8)) >> did;
else
BUG();

return mhz * 1000;
}

static int fill_powernow_table(struct powernow_k8_data *data,
struct pst_s *pst, u8 maxvid)
{
Expand Down Expand Up @@ -923,8 +937,13 @@ static int fill_powernow_table_pstate(struct powernow_k8_data *data,

powernow_table[i].index = index;

powernow_table[i].frequency =
data->acpi_data.states[i].core_frequency * 1000;
/* Frequency may be rounded for these */
if (boot_cpu_data.x86 == 0x10 || boot_cpu_data.x86 == 0x11) {
powernow_table[i].frequency =
freq_from_fid_did(lo & 0x3f, (lo >> 6) & 7);
} else
powernow_table[i].frequency =
data->acpi_data.states[i].core_frequency * 1000;
}
return 0;
}
Expand Down

0 comments on commit ca446d0

Please sign in to comment.