[CPUFREQ] architectural pstate driver for powernow-k8

This patch should apply cleanly to the 2.6.23-git7 kernel.  It changes the
powernow-k8 driver code that deals with 3rd generation Opteron, Phenom,
and later processors to match the architectural pstate driver described
in the AMD64 Architecture Programmer's Manual Volume 2 Chapter 18.  The
initial implementation of the hardware pstate driver for PowerNow!
used some processor-version specific features, and would not be
maintainable in the long term as the processor features changed.
This architectural driver should work on all future AMD processors.
 
Signed-off-by: Mark Langsdorf <mark.langsdorf@amd.com>
Signed-off-by: Andreas Herrmann <andreas.herrmann3@amd.com>
Signed-off-by: Dave Jones <davej@redhat.com>

authored by Mark Langsdorf and committed by Dave Jones c5829cd0 63bd8c48

+29 -81
+23 -67
arch/x86/kernel/cpu/cpufreq/powernow-k8.c
··· 46 46 47 47 #define PFX "powernow-k8: " 48 48 #define BFX PFX "BIOS error: " 49 - #define VERSION "version 2.00.00" 49 + #define VERSION "version 2.20.00" 50 50 #include "powernow-k8.h" 51 51 52 52 /* serialize freq changes */ ··· 73 73 return 1000 * find_freq_from_fid(fid); 74 74 } 75 75 76 - /* Return a frequency in MHz, given an input fid and did */ 77 - static u32 find_freq_from_fiddid(u32 fid, u32 did) 76 + static u32 find_khz_freq_from_pstate(struct cpufreq_frequency_table *data, u32 pstate) 78 77 { 79 - if (current_cpu_data.x86 == 0x10) 80 - return 100 * (fid + 0x10) >> did; 81 - else 82 - return 100 * (fid + 0x8) >> did; 78 + return data[pstate].frequency; 83 79 } 84 80 85 - static u32 find_khz_freq_from_fiddid(u32 fid, u32 did) 86 - { 87 - return 1000 * find_freq_from_fiddid(fid, did); 88 - } 89 - 90 - static u32 find_fid_from_pstate(u32 pstate) 91 - { 92 - u32 hi, lo; 93 - rdmsr(MSR_PSTATE_DEF_BASE + pstate, lo, hi); 94 - return lo & HW_PSTATE_FID_MASK; 95 - } 96 - 97 - static u32 find_did_from_pstate(u32 pstate) 98 - { 99 - u32 hi, lo; 100 - rdmsr(MSR_PSTATE_DEF_BASE + pstate, lo, hi); 101 - return (lo & HW_PSTATE_DID_MASK) >> HW_PSTATE_DID_SHIFT; 102 - } 103 81 104 82 /* Return the vco fid for an input fid 105 83 * ··· 120 142 if (cpu_family == CPU_HW_PSTATE) { 121 143 rdmsr(MSR_PSTATE_STATUS, lo, hi); 122 144 i = lo & HW_PSTATE_MASK; 123 - rdmsr(MSR_PSTATE_DEF_BASE + i, lo, hi); 124 - data->currfid = lo & HW_PSTATE_FID_MASK; 125 - data->currdid = (lo & HW_PSTATE_DID_MASK) >> HW_PSTATE_DID_SHIFT; 145 + data->currpstate = i; 126 146 return 0; 127 147 } 128 148 do { ··· 271 295 static int transition_pstate(struct powernow_k8_data *data, u32 pstate) 272 296 { 273 297 wrmsr(MSR_PSTATE_CTRL, pstate, 0); 274 - data->currfid = find_fid_from_pstate(pstate); 298 + data->currpstate = pstate; 275 299 return 0; 276 300 } 277 301 ··· 821 845 static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table) 822 846 { 823 847 int i; 848 + u32 hi = 0, lo = 0; 849 + rdmsr(MSR_PSTATE_CUR_LIMIT, hi, lo); 850 + data->max_hw_pstate = (hi & HW_PSTATE_MAX_MASK) >> HW_PSTATE_MAX_SHIFT; 824 851 825 852 for (i = 0; i < data->acpi_data.state_count; i++) { 826 853 u32 index; 827 854 u32 hi = 0, lo = 0; 828 - u32 fid; 829 - u32 did; 830 855 831 856 index = data->acpi_data.states[i].control & HW_PSTATE_MASK; 832 - if (index > MAX_HW_PSTATE) { 857 + if (index > data->max_hw_pstate) { 833 858 printk(KERN_ERR PFX "invalid pstate %d - bad value %d.\n", i, index); 834 859 printk(KERN_ERR PFX "Please report to BIOS manufacturer\n"); 860 + powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID; 861 + continue; 835 862 } 836 863 rdmsr(MSR_PSTATE_DEF_BASE + index, lo, hi); 837 864 if (!(hi & HW_PSTATE_VALID_MASK)) { ··· 843 864 continue; 844 865 } 845 866 846 - fid = lo & HW_PSTATE_FID_MASK; 847 - did = (lo & HW_PSTATE_DID_MASK) >> HW_PSTATE_DID_SHIFT; 867 + powernow_table[i].index = index; 848 868 849 - dprintk(" %d : fid 0x%x, did 0x%x\n", index, fid, did); 850 - 851 - powernow_table[i].index = index | (fid << HW_FID_INDEX_SHIFT) | (did << HW_DID_INDEX_SHIFT); 852 - 853 - powernow_table[i].frequency = find_khz_freq_from_fiddid(fid, did); 854 - 855 - if (powernow_table[i].frequency != (data->acpi_data.states[i].core_frequency * 1000)) { 856 - printk(KERN_INFO PFX "invalid freq entries %u kHz vs. %u kHz\n", 857 - powernow_table[i].frequency, 858 - (unsigned int) (data->acpi_data.states[i].core_frequency * 1000)); 859 - powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID; 860 - continue; 861 - } 869 + powernow_table[i].frequency = data->acpi_data.states[i].core_frequency * 1000; 862 870 } 863 871 return 0; 864 872 } ··· 986 1020 /* Take a frequency, and issue the hardware pstate transition command */ 987 1021 static int transition_frequency_pstate(struct powernow_k8_data *data, unsigned int index) 988 1022 { 989 - u32 fid = 0; 990 - u32 did = 0; 991 1023 u32 pstate = 0; 992 1024 int res, i; 993 1025 struct cpufreq_freqs freqs; 994 1026 995 1027 dprintk("cpu %d transition to index %u\n", smp_processor_id(), index); 996 1028 997 - /* get fid did for hardware pstate transition */ 1029 + /* get MSR index for hardware pstate transition */ 998 1030 pstate = index & HW_PSTATE_MASK; 999 - if (pstate > MAX_HW_PSTATE) 1031 + if (pstate > data->max_hw_pstate) 1000 1032 return 0; 1001 - fid = (index & HW_FID_INDEX_MASK) >> HW_FID_INDEX_SHIFT; 1002 - did = (index & HW_DID_INDEX_MASK) >> HW_DID_INDEX_SHIFT; 1003 - freqs.old = find_khz_freq_from_fiddid(data->currfid, data->currdid); 1004 - freqs.new = find_khz_freq_from_fiddid(fid, did); 1033 + freqs.old = find_khz_freq_from_pstate(data->powernow_table, data->currpstate); 1034 + freqs.new = find_khz_freq_from_pstate(data->powernow_table, pstate); 1005 1035 1006 1036 for_each_cpu_mask(i, *(data->available_cores)) { 1007 1037 freqs.cpu = i; ··· 1005 1043 } 1006 1044 1007 1045 res = transition_pstate(data, pstate); 1008 - data->currfid = find_fid_from_pstate(pstate); 1009 - data->currdid = find_did_from_pstate(pstate); 1010 - freqs.new = find_khz_freq_from_fiddid(data->currfid, data->currdid); 1046 + freqs.new = find_khz_freq_from_pstate(data->powernow_table, pstate); 1011 1047 1012 1048 for_each_cpu_mask(i, *(data->available_cores)) { 1013 1049 freqs.cpu = i; ··· 1050 1090 if (query_current_values_with_pending_wait(data)) 1051 1091 goto err_out; 1052 1092 1053 - if (cpu_family == CPU_HW_PSTATE) 1054 - dprintk("targ: curr fid 0x%x, did 0x%x\n", 1055 - data->currfid, data->currdid); 1056 - else { 1093 + if (cpu_family != CPU_HW_PSTATE) { 1057 1094 dprintk("targ: curr fid 0x%x, vid 0x%x\n", 1058 1095 data->currfid, data->currvid); 1059 1096 ··· 1081 1124 mutex_unlock(&fidvid_mutex); 1082 1125 1083 1126 if (cpu_family == CPU_HW_PSTATE) 1084 - pol->cur = find_khz_freq_from_fiddid(data->currfid, data->currdid); 1127 + pol->cur = find_khz_freq_from_pstate(data->powernow_table, newstate); 1085 1128 else 1086 1129 pol->cur = find_khz_freq_from_fid(data->currfid); 1087 1130 ret = 0; ··· 1180 1223 + (3 * (1 << data->irt) * 10)) * 1000; 1181 1224 1182 1225 if (cpu_family == CPU_HW_PSTATE) 1183 - pol->cur = find_khz_freq_from_fiddid(data->currfid, data->currdid); 1226 + pol->cur = find_khz_freq_from_pstate(data->powernow_table, data->currpstate); 1184 1227 else 1185 1228 pol->cur = find_khz_freq_from_fid(data->currfid); 1186 1229 dprintk("policy current frequency %d kHz\n", pol->cur); ··· 1197 1240 cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu); 1198 1241 1199 1242 if (cpu_family == CPU_HW_PSTATE) 1200 - dprintk("cpu_init done, current fid 0x%x, did 0x%x\n", 1201 - data->currfid, data->currdid); 1243 + dprintk("cpu_init done, current pstate 0x%x\n", data->currpstate); 1202 1244 else 1203 1245 dprintk("cpu_init done, current fid 0x%x, vid 0x%x\n", 1204 1246 data->currfid, data->currvid); ··· 1253 1297 goto out; 1254 1298 1255 1299 if (cpu_family == CPU_HW_PSTATE) 1256 - khz = find_khz_freq_from_fiddid(data->currfid, data->currdid); 1300 + khz = find_khz_freq_from_pstate(data->powernow_table, data->currpstate); 1257 1301 else 1258 1302 khz = find_khz_freq_from_fid(data->currfid); 1259 1303
+6 -14
arch/x86/kernel/cpu/cpufreq/powernow-k8.h
··· 10 10 11 11 u32 numps; /* number of p-states */ 12 12 u32 batps; /* number of p-states supported on battery */ 13 + u32 max_hw_pstate; /* maximum legal hardware pstate */ 13 14 14 15 /* these values are constant when the PSB is used to determine 15 16 * vid/fid pairings, but are modified during the ->target() call ··· 22 21 u32 plllock; /* pll lock time, units 1 us */ 23 22 u32 exttype; /* extended interface = 1 */ 24 23 25 - /* keep track of the current fid / vid or did */ 26 - u32 currvid, currfid, currdid; 24 + /* keep track of the current fid / vid or pstate */ 25 + u32 currvid, currfid, currpstate; 27 26 28 27 /* the powernow_table includes all frequency and vid/fid pairings: 29 28 * fid are the lower 8 bits of the index, vid are the upper 8 bits. ··· 88 87 89 88 /* Hardware Pstate _PSS and MSR definitions */ 90 89 #define USE_HW_PSTATE 0x00000080 91 - #define HW_PSTATE_FID_MASK 0x0000003f 92 - #define HW_PSTATE_DID_MASK 0x000001c0 93 - #define HW_PSTATE_DID_SHIFT 6 94 90 #define HW_PSTATE_MASK 0x00000007 95 91 #define HW_PSTATE_VALID_MASK 0x80000000 96 - #define HW_FID_INDEX_SHIFT 8 97 - #define HW_FID_INDEX_MASK 0x0000ff00 98 - #define HW_DID_INDEX_SHIFT 16 99 - #define HW_DID_INDEX_MASK 0x00ff0000 100 - #define HW_WATTS_MASK 0xff 101 - #define HW_PWR_DVR_MASK 0x300 102 - #define HW_PWR_DVR_SHIFT 8 103 - #define HW_PWR_MAX_MULT 3 104 - #define MAX_HW_PSTATE 8 /* hw pstate supports up to 8 */ 92 + #define HW_PSTATE_MAX_MASK 0x000000f0 93 + #define HW_PSTATE_MAX_SHIFT 4 105 94 #define MSR_PSTATE_DEF_BASE 0xc0010064 /* base of Pstate MSRs */ 106 95 #define MSR_PSTATE_STATUS 0xc0010063 /* Pstate Status MSR */ 107 96 #define MSR_PSTATE_CTRL 0xc0010062 /* Pstate control MSR */ 97 + #define MSR_PSTATE_CUR_LIMIT 0xc0010061 /* pstate current limit MSR */ 108 98 109 99 /* define the two driver architectures */ 110 100 #define CPU_OPTERON 0