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