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